<?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: Damilare Osibanjo</title>
    <description>The latest articles on DEV Community by Damilare Osibanjo (@dev-dami).</description>
    <link>https://dev.to/dev-dami</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%2F3504454%2Fb2f41c02-8f47-4af0-ac81-c9d4d74f304a.png</url>
      <title>DEV Community: Damilare Osibanjo</title>
      <link>https://dev.to/dev-dami</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dev-dami"/>
    <language>en</language>
    <item>
      <title>I Got Mad at an npm Hack, Spent 3 Days Yelling at an AI, and Accidentally Built a Library 4 Faster Than Axios</title>
      <dc:creator>Damilare Osibanjo</dc:creator>
      <pubDate>Mon, 06 Apr 2026 20:05:15 +0000</pubDate>
      <link>https://dev.to/dev-dami/i-got-mad-at-an-npm-hack-spent-3-days-yelling-at-an-ai-and-accidentally-built-a-library-4-faster-1bld</link>
      <guid>https://dev.to/dev-dami/i-got-mad-at-an-npm-hack-spent-3-days-yelling-at-an-ai-and-accidentally-built-a-library-4-faster-1bld</guid>
      <description>&lt;p&gt;So. The axios hack.&lt;/p&gt;

&lt;p&gt;If you missed it quick recap, a week ago, the maintainer’s account got compromised. Hackers slipped in a postinstall script that quietly reached into machines and siphoned cloud credentials, API keys, and crypto wallets. The kind of breach that makes you stare at your &lt;code&gt;node_modules&lt;/code&gt; folder with profound suspicion.&lt;/p&gt;

&lt;p&gt;Now, I’m sitting there reading the incident report and something itches at the back of my brain.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why does axios - a client-side HTTP library have any dependencies at all?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I went digging. And yeah. I was right. Axios ships with a non-trivial dependency tree, a &lt;code&gt;postinstall&lt;/code&gt; surface, and ~14KB of gzipped bundle weight. For something that fundamentally just wraps &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;http&lt;/code&gt;. That’s not a library. That’s a small town.&lt;/p&gt;

&lt;p&gt;So I did what any reasonable developer does when they’re mildly annoyed at 11pm: I opened a new project folder and decided to fix it myself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 1: “How Hard Can It Be”
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;(Famous last words. All great disasters start with these four words.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I fired up &lt;a href="//dev.to/dami"&gt;Qwen Coder 3.6&lt;/a&gt; — a model I’ve been putting through its paces lately and honestly? It’s become one of my favourite tools to work with. Different vibe from the usual suspects, really solid at systems-level reasoning. Full breakdown in a separate post coming soon, but the short version is: it can steer code the way you want it steered.&lt;/p&gt;

&lt;p&gt;The pitch for &lt;code&gt;kiattp&lt;/code&gt; was simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero dependencies. Not “few dependencies.” &lt;strong&gt;Zero.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;No postinstall scripts. Ever.&lt;/li&gt;
&lt;li&gt;Drop-in axios replacement — so nobody has to refactor their entire codebase&lt;/li&gt;
&lt;li&gt;Fast. Like, embarrassingly fast compared to what we’ve been tolerating&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three days of steering, testing, profiling, and arguing with benchmarks later — we had something.&lt;/p&gt;




&lt;h2&gt;
  
  
  v0.1.0: It Worked. It Was Fast. I Was Briefly Smug.
&lt;/h2&gt;

&lt;p&gt;The first version cleared 4,000 ops/sec against axios’s ~940 in MSW mock benchmarks. That’s roughly &lt;strong&gt;4× faster&lt;/strong&gt;. The bundle came in at ~3.7KB gzipped. No deps. No postinstall.&lt;/p&gt;

&lt;p&gt;I celebrated for maybe twenty minutes.&lt;/p&gt;

&lt;p&gt;Then I started stress-testing the axios compatibility layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bug That Humbled Me
&lt;/h2&gt;

&lt;p&gt;Here’s the thing about drop-in replacements: users don’t &lt;em&gt;tell&lt;/em&gt; you how they’re using the original. They just swap it in and expect everything to work. And if it doesn’t? They don’t file issues. They just quietly go back to the old library and never mention it.&lt;/p&gt;

&lt;p&gt;So I was testing a project that used &lt;code&gt;axios.create()&lt;/code&gt; with a &lt;code&gt;baseURL&lt;/code&gt;, and I noticed something cursed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// This worked fine ✅&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This completely ignored baseURL ❌&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second call sent a request to &lt;code&gt;/users&lt;/code&gt;. Just… bare &lt;code&gt;/users&lt;/code&gt;. Into the void.&lt;/p&gt;

&lt;p&gt;Turns out when the request path starts with &lt;code&gt;/&lt;/code&gt;, my compatibility layer was treating it as an absolute path and skipping the &lt;code&gt;baseURL&lt;/code&gt; concatenation entirely. Which is wrong. Which is how axios actually works. Which I did not implement correctly.&lt;/p&gt;

&lt;p&gt;This is the part of the story where I remind you that axios has been battle-tested for years by millions of developers, and I had been working on my replacement for approximately 72 hours.&lt;/p&gt;

&lt;p&gt;Humbling.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fixing It (Without Wrecking Performance)
&lt;/h2&gt;

&lt;p&gt;The fix sounds simple: if there’s a &lt;code&gt;baseURL&lt;/code&gt; and the path starts with &lt;code&gt;/&lt;/code&gt;, still prepend the base. Strip the trailing slash from &lt;code&gt;baseURL&lt;/code&gt;, strip the leading slash from the path, join them cleanly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&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;base&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;path&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;+$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="s2"&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;Six lines. But the performance implications of &lt;em&gt;where&lt;/em&gt; you do this normalization are non-trivial. URL construction sits in the hot path of every single request. Do it wrong and you’re allocating strings everywhere, blowing up the CPU cache, killing your ops/sec.&lt;/p&gt;

&lt;p&gt;It took several iterations to land on an approach that kept performance at spec. The final numbers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;ops/sec&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;th&gt;p99&lt;/th&gt;
&lt;th&gt;Size (gzipped)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;kiattp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~4,000&lt;/td&gt;
&lt;td&gt;0.25ms&lt;/td&gt;
&lt;td&gt;0.80ms&lt;/td&gt;
&lt;td&gt;~3.7KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;axios&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~940&lt;/td&gt;
&lt;td&gt;1.07ms&lt;/td&gt;
&lt;td&gt;4.83ms&lt;/td&gt;
&lt;td&gt;~14KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;native fetch&lt;/td&gt;
&lt;td&gt;~6,100&lt;/td&gt;
&lt;td&gt;0.16ms&lt;/td&gt;
&lt;td&gt;0.32ms&lt;/td&gt;
&lt;td&gt;0KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Yes, native fetch is faster. It should be. It’s a browser primitive. The ~0.09ms overhead we add over fetch is the cost of config normalization, interceptors, error handling, and not having to write 50 lines of boilerplate per request. That’s a good trade.&lt;/p&gt;




&lt;h2&gt;
  
  
  What kiattp Actually Does
&lt;/h2&gt;

&lt;p&gt;Beyond “axios but fast and small,” here’s what the library actually ships with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero-dep, zero-drama installs:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;kiattp
&lt;span class="c"&gt;# No postinstall. No audit warnings. No surprise scripts.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The same API you already know:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createInstance&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;kiattp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createInstance&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bearer token&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&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="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// yes, the slash works now&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Full axios compatibility layer&lt;/strong&gt; — drop it in as a replacement without touching your codebase:&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;axios&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;kiattp/axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// CancelToken, isCancel, isAxiosError, all, spread — all there&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A plugin system&lt;/strong&gt; instead of baking everything into the core:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;retry_plugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;backoff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exponential&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;jitter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;logger_plugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}));&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;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;timeout_plugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Interceptors&lt;/strong&gt; that work exactly like you’d expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;config&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bearer &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;getToken&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;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&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;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&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;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;err&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;&lt;strong&gt;Binary and streaming responses, upload/download progress, XSRF support, Node.js http adapter with proxy and redirect control&lt;/strong&gt; the full table is in the README, I’ll spare you the exhaustive spec dump here.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Security Angle Is Actually The Point
&lt;/h2&gt;

&lt;p&gt;I want to come back to where this started, because I think it matters.&lt;/p&gt;

&lt;p&gt;The axios attack vector was specifically the dependency tree and the postinstall hook. That’s the surface that got exploited. A library with no dependencies and no postinstall scripts has a fundamentally smaller attack surface. Not zero nothing is zero but meaningfully smaller.&lt;/p&gt;

&lt;p&gt;When you &lt;code&gt;npm install kiattp&lt;/code&gt;, you get exactly what’s in the kiattp package. There’s no &lt;code&gt;follow-redirects&lt;/code&gt; to get compromised. No &lt;code&gt;form-data&lt;/code&gt; to inherit vulnerabilities from. No mysterious &lt;code&gt;postinstall&lt;/code&gt; script touching your filesystem.&lt;/p&gt;

&lt;p&gt;Supply chain security isn’t just a DevSecOps team’s problem anymore. It’s a library author’s design decision. And I think the default should be: if you don’t need a dependency, don’t have one.&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;p&gt;The library is live. Benchmarks are reproducible, the BENCHMARK.md has full methodology if you want to verify or poke holes in the numbers.&lt;/p&gt;

&lt;p&gt;Subpath exports are set up so you can pull in only what you need:&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;httpAdapter&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;kiattp/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;           &lt;span class="c1"&gt;// Node.js adapter only&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;retry_plugin&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;kiattp/plugins/retry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// just the plugin&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;axios&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;kiattp/axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                &lt;span class="c1"&gt;// just the compat layer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ll be doing a follow-up post on the Qwen Coder 3.6 workflow — specifically how I structured the steering prompts and the test harness to keep the model producing output that actually benchmarks well rather than just looks right. There’s a real art to using it effectively.&lt;/p&gt;

&lt;p&gt;For now: try it, break it, file issues, tell me what the axios compat layer is missing for your use case. That’s the only way this gets properly battle-tested.&lt;/p&gt;






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

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/dev-dami/kiattp" rel="noopener noreferrer"&gt;dev-dami/kiattp&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Thanks for reading. If you enjoyed this, the post on Qwen Coder 3.6 is coming soon and yes, I did use it to help build the very library this post is about. The recursion is not lost on me.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
