<?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: Samuel Karani</title>
    <description>The latest articles on DEV Community by Samuel Karani (@samuelkarani).</description>
    <link>https://dev.to/samuelkarani</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%2F386546%2Fd792a4c1-99d6-44bd-9d9e-332a547b7baf.jpeg</url>
      <title>DEV Community: Samuel Karani</title>
      <link>https://dev.to/samuelkarani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samuelkarani"/>
    <language>en</language>
    <item>
      <title>arrays-sugar provides async versions of javascript array methods with predicate callbacks</title>
      <dc:creator>Samuel Karani</dc:creator>
      <pubDate>Thu, 31 Jul 2025 20:21:19 +0000</pubDate>
      <link>https://dev.to/samuelkarani/arrays-sugar-provides-async-versions-of-javascript-array-methods-with-predicate-callbacks-29gj</link>
      <guid>https://dev.to/samuelkarani/arrays-sugar-provides-async-versions-of-javascript-array-methods-with-predicate-callbacks-29gj</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR: This article introduces the arrays-sugar library: &lt;a href="https://github.com/samuelkarani/arrays-sugar" rel="noopener noreferrer"&gt;https://github.com/samuelkarani/arrays-sugar&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why won't this work correctly in javascript?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const array = [1, 7, 3]
array.every(async (number) =&amp;gt; number &amp;gt; 1) // returns true instead of false
array.filter(async (number) =&amp;gt; number &amp;gt; 1) // returns [1, 7, 3] instead of ?
array.find(async (number) =&amp;gt; number &amp;gt; 1) // returns 1 instead of ?
array.findIndex(async (number) =&amp;gt; number &amp;gt; 1) // returns 0 instead of ?
array.some(async (number) =&amp;gt; number &amp;gt; 7) // returns true instead of ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All these return incorrect values because the &lt;code&gt;async&lt;/code&gt; makes the callback return a &lt;code&gt;promise&lt;/code&gt; which always returns truthy when evaluated.&lt;/p&gt;

&lt;p&gt;While &lt;code&gt;map&lt;/code&gt; is happy to give you as many promises as you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;array.map(async (number) =&amp;gt; number * 2)
// [ Promise { 2 }, Promise { 14 }, Promise { 6 } ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;reduce&lt;/code&gt; works with both &lt;code&gt;promise&lt;/code&gt; and &lt;code&gt;async/await&lt;/code&gt; callbacks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const numbers = [1, 2, 3, 4, 5];

const sum1 = await numbers.reduce((accumulator, number) =&amp;gt; {
  return accumulator.then(value =&amp;gt; value + number)
}, Promise.resolve(0));
// sum1 is 15

const sum2 = await numbers.reduce(async (accumulator, number) =&amp;gt; {
  await sleep(10) // wraps setTimeout
  return (await accumulator) + number;
}, Promise.resolve(0))
// sum2 is 15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Introducing my new library: &lt;strong&gt;arrays-sugar&lt;/strong&gt; - a set of async versions of &lt;code&gt;every&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;, &lt;code&gt;findIndex&lt;/code&gt;, &lt;code&gt;some&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Build with Typescript for the Browser or Node.js&lt;/p&gt;

&lt;p&gt;Each function has 2 or 3 versions:&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;default&lt;/strong&gt; version that is concurrent and uses &lt;code&gt;Promise.allSettled&lt;/code&gt; internally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// both are equivalent
   [1, 2, 3].every(async (number) =&amp;gt; number === 2) === true
   [1, 2, 3].everyConcurrent(async (number) =&amp;gt; number === 2) === true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;optimized&lt;/strong&gt; version which may not iterate the entire array and requires that the predicate &lt;code&gt;throws&lt;/code&gt; for falsy values instead of returning &lt;code&gt;false&lt;/code&gt;. This is available for all functions except &lt;code&gt;filter&lt;/code&gt; which has to go through the whole array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const result = await findOptimized(array, async (item) =&amp;gt; {
      if (item &amp;lt;= 1) {
        throw new Error("error");
      }
      return true;
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;serial&lt;/strong&gt; version that iterates each item one at a time (slow) - incase this is what you want to do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const result = await findIndexSerial(array, async (item) =&amp;gt; {
      await sleep(100);
      return item &amp;gt; 1;
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That's all&lt;/strong&gt;&lt;br&gt;
Thanks for reading. I welcome your input, suggestions, feedback.&lt;br&gt;
Github link: &lt;a href="https://github.com/samuelkarani/arrays-sugar" rel="noopener noreferrer"&gt;https://github.com/samuelkarani/arrays-sugar&lt;/a&gt;&lt;br&gt;
NPM link: &lt;a href="https://www.npmjs.com/package/arrays-sugar" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/arrays-sugar&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One more thing&lt;/strong&gt;&lt;br&gt;
You can check out the related library &lt;a href="https://github.com/samuelkarani/ai-sugar" rel="noopener noreferrer"&gt;AI Sugar&lt;/a&gt; where these functions are used internally to work with AI APIs.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>zod-sugar is just ‘zod backwards’ or “zod in reverse”</title>
      <dc:creator>Samuel Karani</dc:creator>
      <pubDate>Thu, 31 Jul 2025 19:36:18 +0000</pubDate>
      <link>https://dev.to/samuelkarani/zod-sugar-is-just-zod-backwards-or-zod-in-reverse-44gb</link>
      <guid>https://dev.to/samuelkarani/zod-sugar-is-just-zod-backwards-or-zod-in-reverse-44gb</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR: This article introduces the zod-sugar library: &lt;a href="https://github.com/samuelkarani/zod-sugar" rel="noopener noreferrer"&gt;https://github.com/samuelkarani/zod-sugar&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When building my newly released &lt;a href="https://github.com/samuelkarani/ai-sugar" rel="noopener noreferrer"&gt;ai-sugar&lt;/a&gt; library, I came across a use case where I needed to create a zod schema from a value -  instead of the usual case where you define your schema then parse your value with it. So I made I library for it and released it for the world on &lt;a href="https://www.npmjs.com/package/zod-sugar" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's example of how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createZod } from "zod-sugar";

const object = {
   foo: "bar",
   bar: 1,
   baz: [1, 2, 3],
   qux: { foo: "bar" },
}
const schema = createZod(object);
// schema is a ZodObject
const result = schema.safeParse(object);
// result.success === true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works with common javascript values: null, undefined, boolean, number, bigint, string, symbol, array, object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;createZod(null) // ZodNull

createZod(undefined) // ZodUndefined

createZod(1) // ZodNumber

createZod("foo") // ZodString

createZod(false) // ZodBoolean

createZod(Symbol("foo")) // ZodSymbol

createZod(BigInt(1)) // ZodBigInt

createZod([1, 2, 3]) // ZodArray

createZod({ foo: "bar", baz: 1 }) // ZodObject

createZod({
 string: "bar",
 number: 1,
 array: [1, 2, 3],
 bigint: BigInt(9007199254740991),
 object: {
    number: 0,
    boolean: false,
    object: {
       string: "bar",
       null: null,
       [Symbol("foo")]: "bar",
    },
    array: ["1", "2", "3"],
 },
undefined: undefined,
}) // ZodObject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install it simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install zod-sugar
yarn add zod-sugar
pnpm install zod-sugar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;br&gt;
AI Sugar is the related library where these functions are used internally to work with AI APIs: &lt;a href="https://github.com/samuelkarani/ai-sugar" rel="noopener noreferrer"&gt;https://github.com/samuelkarani/ai-sugar&lt;/a&gt;&lt;br&gt;
Github link: &lt;a href="https://github.com/samuelkarani/zod-sugar" rel="noopener noreferrer"&gt;https://github.com/samuelkarani/zod-sugar&lt;/a&gt;&lt;br&gt;
NPM link: &lt;a href="https://www.npmjs.com/package/zod-sugar" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/zod-sugar&lt;/a&gt;&lt;/p&gt;

</description>
      <category>zod</category>
      <category>schema</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to setup Vercel AI Function Streaming with CORS support</title>
      <dc:creator>Samuel Karani</dc:creator>
      <pubDate>Thu, 31 Jul 2025 19:02:04 +0000</pubDate>
      <link>https://dev.to/samuelkarani/how-to-setup-vercel-ai-function-streaming-with-cors-support-39g9</link>
      <guid>https://dev.to/samuelkarani/how-to-setup-vercel-ai-function-streaming-with-cors-support-39g9</guid>
      <description>&lt;p&gt;Vercel seems to have abandoned or deprioritized their serverless functions offering (outside Next.js) because I couldn’t find any official documentation for setting up function streaming with CORS enabled.&lt;/p&gt;

&lt;p&gt;Eventually this ended up being quite a hassle to figure out, so I decided to make this snippet for anyone who needs it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { openai } from "@ai-sdk/openai";
import { streamText } from "ai";

export function OPTIONS() {
  return new Response("OK", {
    status: 200,
    headers: {
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "GET,OPTIONS,PATCH,DELETE,POST,PUT",
      "Access-Control-Allow-Headers":
        "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
    },
  });
}

export async function GET() {
  const response = streamText({
    model: openai("gpt-4o-mini"),
    messages: [{ role: "user", content: "Write a short poem" }],
  });
  return response.toTextStreamResponse({
    headers: {
      "Content-Type": "text/event-stream",
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "GET,OPTIONS,PATCH,DELETE,POST,PUT",
      "Access-Control-Allow-Headers":
        "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
    },
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>vercel</category>
      <category>ai</category>
      <category>streaming</category>
      <category>node</category>
    </item>
  </channel>
</rss>
