<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" xml:base="https://www.andyjarrett.com//" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>AndyJarrett.com</title>
    <link>https://www.andyjarrett.com//</link>
    <description>Posts about web app development</description>
    <language>en</language>
    <atom:link href="https://www.andyjarrett.com//feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Reclaiming Space on macOS from Docker by Pruning Docker.raw</title>
      <link>https://www.andyjarrett.com/posts/2024/reclaiming-space-on-macos-from-docker-by-pruning-docker-raw/</link>
      <description><![CDATA[
&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/nathan-cima-2JNNpq4nGls-unsplash.jpg&quot; alt=&quot;Developer debugging&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;Photo by &lt;a href=&quot;https://unsplash.com/@nathan_cima?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Nathan Cima&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/a-large-ship-in-the-water-2JNNpq4nGls?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;

&lt;p&gt;Docker on macOS stores its container data in a virtual disk file called &lt;code&gt;Docker.raw&lt;/code&gt;. This file is used by Docker&#39;s internal virtual machine (VM) and can grow dynamically as more containers and images are created. Over time, even when containers are deleted, &lt;code&gt;Docker.raw&lt;/code&gt; can take up substantial disk space.&lt;/p&gt;

&lt;p&gt;I recently encountered this issue, where my &lt;code&gt;Docker.raw&lt;/code&gt; file showed a size of 60G:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ls -lh ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, the actual disk usage was 31G:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ du -sh ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The discrepancy occurs because &lt;code&gt;Docker.raw&lt;/code&gt; is a sparse file. While it can potentially use 60G, it only occupies 31G of actual disk space.&lt;/p&gt;

&lt;p&gt;To reclaim space, you can clean up unused data with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ docker system prune&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note: Space is only freed when images are deleted. Space inside running containers is not automatically reclaimed. To trigger space reclamation, run:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ docker run --privileged --pid=host docker/desktop-reclaim-space&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For more details, refer to the official Docker documentation: &lt;a href=&quot;https://docs.docker.com/desktop/faqs/macfaqs/&quot;&gt;Docker Desktop FAQs for macOS&lt;/a&gt;.&lt;/p&gt;]]></description>
      <pubDate>Thu, 29 Aug 2024 22:02:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2024/reclaiming-space-on-macos-from-docker-by-pruning-docker-raw/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/nathan-cima-2JNNpq4nGls-unsplash.jpg" type="image/jpeg" />
      <category>posts, docker, macos, disk space, docker.raw, system maintenance</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>Bluesky now has over 10 million users, and I was #56,137!</title>
      <link>https://www.andyjarrett.com/posts/2024/bluesky-now-has-over-10-million-users-and-i-was-number-56137/</link>
      <description><![CDATA[
&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/adam-birkett-P2ah-LaV52I-unsplash.jpg&quot; alt=&quot;Developer debugging&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;Photo by &lt;a href=&quot;https://unsplash.com/@abrkett?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Adam Birkett&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/white-and-black-light-post-under-blue-sky-P2ah-LaV52I?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;col-12&quot;&gt;
    &lt;p&gt;Bluesky now has over 10 million users, and I was  &lt;a href=&quot;https://bsky.app/profile/andyjarrett.com&quot;&gt;#56137&lt;/a&gt;!&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;row mb-5&quot;&gt;
  &lt;div class=&quot;col-6&quot;&gt;
    &lt;a href=&quot;https://bsky.app/profile/andyjarrett.com&quot;&gt;
      &lt;img src=&quot;https://www.andyjarrett.com/public/img/bluesky-andyjarrett.png&quot; alt=&quot;A virtual certificate with text &#39;Celebrating 10M users on Bluesky, #56,137, Andy Jarrett @andyjarrett.com, joined on May 3, 2023&#39;&quot; class=&quot;img-fluid&quot; /&gt;
    &lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;]]></description>
      <pubDate>Mon, 16 Sep 2024 17:01:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2024/bluesky-now-has-over-10-million-users-and-i-was-number-56137/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/adam-birkett-P2ah-LaV52I-unsplash.jpg" type="image/jpeg" />
      <category>posts, bluesky, 10million</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>Understanding Variable Scoping Differences Between Lucee 5 and Lucee 6</title>
      <link>https://www.andyjarrett.com/posts/2024/understanding-variable-scoping-differences-between-lucee-5-and-lucee-6/</link>
      <description><![CDATA[



&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/lewis-kang-ethe-ngugi-f5pTwLHCsAg-unsplash.jpg&quot; alt=&quot;Computer with code&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;
      Photo by &lt;a href=&quot;https://unsplash.com/@brina_blum?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Brina Blum&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/black-usb-flash-drive-Bb_X4JgSqIM?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;
    &lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;


  &lt;h1 class=&quot;mb-4&quot;&gt;&lt;/h1&gt;
  &lt;p&gt;
    From a conversation on the &lt;a href=&quot;https://workingcode.dev/&quot;&gt;Working Code Podcast&lt;/a&gt; &lt;a href=&quot;https://workingcode.dev/discord/&quot;&gt;Discord&lt;/a&gt; channel I came across
    a change between Lucee 5 to Lucee 6, and how variables are scoped and handled, specifically when/if using &lt;code&gt;var&lt;/code&gt; in a &lt;code&gt;.cfm&lt;/code&gt; template.
    This post is just the sample code I used to do some digging on how the scoping differences between the two versions using a simple test cases to show the different outcomes&lt;/p&gt;

  &lt;h2&gt;Test Scenario&lt;/h2&gt;
  &lt;p&gt;Here are my test files, &lt;code&gt;var.cfm&lt;/code&gt; and &lt;code&gt;varinclude.cfm&lt;/code&gt;.&lt;/p&gt;

  &lt;h3&gt;&lt;code&gt;var.cfm&lt;/code&gt; (main template):&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;&amp;lt;cfscript&amp;gt;
  var a = &quot;a&quot;;
  b = &quot;b&quot;;
  local.c = &quot;c&quot;;

  dump(a); // Output: &quot;a&quot;
  dump(b); // Output: &quot;b&quot;
  dump(c); // Output: &quot;c&quot;
  dump(local.c); // Output: &quot;c&quot;

  cfinclude(template=&quot;varinclude.cfm&quot;);
&amp;lt;/cfscript&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

  &lt;h3&gt;&lt;code&gt;varinclude.cfm&lt;/code&gt; (included template):&lt;/h3&gt;
  &lt;pre&gt;&lt;code&gt;&amp;lt;cfscript&amp;gt;
  dump(a); // Output: &quot;a&quot;
  dump(b); // Output: &quot;b&quot;
  dump(c); // Output: &quot;c&quot;
  dump(local.c); // Output: &quot;c&quot;
&amp;lt;/cfscript&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;This setup works well on &lt;strong&gt;Lucee 5&lt;/strong&gt;, where:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;The &lt;code&gt;var&lt;/code&gt; keyword is used to declare variables with function-local scope, even outside functions.&lt;/li&gt;
    &lt;li&gt;The variable &lt;code&gt;b&lt;/code&gt; is implicitly scoped to the current page.&lt;/li&gt;
    &lt;li&gt;The &lt;code&gt;local&lt;/code&gt; scope is explicitly used for &lt;code&gt;c&lt;/code&gt;.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h2&gt;Results on Lucee 5&lt;/h2&gt;
  &lt;p&gt;On Lucee 5, the following outputs occur:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;code&gt;dump(a);&lt;/code&gt; outputs &lt;code&gt;&quot;a&quot;&lt;/code&gt;.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;dump(b);&lt;/code&gt; outputs &lt;code&gt;&quot;b&quot;&lt;/code&gt;.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;dump(c);&lt;/code&gt; outputs &lt;code&gt;&quot;c&quot;&lt;/code&gt;.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;dump(local.c);&lt;/code&gt; outputs &lt;code&gt;&quot;c&quot;&lt;/code&gt;.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;img src=&quot;https://www.andyjarrett.com/public/postimages/understanding-variable-scoping-differences-between-lucee-5-and-lucee-6.img1.png&quot; alt=&quot;Output results&quot; /&gt;

  &lt;p&gt;The included template (&lt;code&gt;varinclude.cfm&lt;/code&gt;) inherits these variables, and everything behaves as expected. This is because, in Lucee 5, &lt;code&gt;var&lt;/code&gt; declarations work even outside of functions.&lt;/p&gt;

  &lt;h2&gt;Behaviour in Lucee 6&lt;/h2&gt;
  &lt;p&gt;When upgrading to &lt;strong&gt;Lucee 6&lt;/strong&gt;, however, some changes in scoping rules cause issues:&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;
      &lt;p&gt;&lt;strong&gt;Using &lt;code&gt;var&lt;/code&gt; outside a function:&lt;/strong&gt;&lt;/p&gt;
      &lt;pre&gt;&lt;code&gt;&amp;lt;cfscript&amp;gt;
  var a = &quot;a&quot;; // This line fails with &quot;Can&#39;t invoke key A, Local Scope can only be invoked inside a Function&quot;
&amp;lt;/cfscript&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;p&gt;In Lucee 6, the &lt;code&gt;var&lt;/code&gt; keyword is now restricted to function scopes, and attempting to use it outside a function will result in an error. This is a notable shift from Lucee 5. &lt;/p&gt;
      &lt;p&gt;&lt;img src=&quot;https://www.andyjarrett.com/public/postimages/understanding-variable-scoping-differences-between-lucee-5-and-lucee-6.img2.png&quot; alt=&quot;Output results&quot; /&gt;&lt;/p&gt;
    &lt;/li&gt;

    &lt;li&gt;
      &lt;p&gt;&lt;strong&gt;Accessing &lt;code&gt;c&lt;/code&gt; without scoping:&lt;/strong&gt;&lt;/p&gt;
      &lt;pre&gt;&lt;code&gt;&amp;lt;cfscript&amp;gt;
  dump(c); // This line fails with &quot;variable [C] doesn&#39;t exist&quot;
&amp;lt;/cfscript&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;p&gt;Lucee 6 enforces stricter scoping rules. Without explicitly declaring &lt;code&gt;c&lt;/code&gt; in a shared scope (such as &lt;code&gt;local.c&lt;/code&gt;), it&#39;s no longer accessible in the same way as in Lucee 5.&lt;/p&gt;
      &lt;p&gt; &lt;img src=&quot;https://www.andyjarrett.com/public/postimages/understanding-variable-scoping-differences-between-lucee-5-and-lucee-6.img3.png&quot; alt=&quot;Output results&quot; /&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;



  &lt;h2&gt;TL;DR&lt;/h2&gt;
  &lt;p&gt;When migrating from Lucee 5 to Lucee 6, developers need to be aware of the stricter scoping rules.
    &lt;strong&gt;&lt;code&gt;var&lt;/code&gt; is now restricted to function scope in Lucee 6&lt;/strong&gt;. Attempting to use it outside of a function will result in an error.
  &lt;/p&gt;
]]></description>
      <pubDate>Wed, 09 Oct 2024 07:28:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2024/understanding-variable-scoping-differences-between-lucee-5-and-lucee-6/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/lewis-kang-ethe-ngugi-f5pTwLHCsAg-unsplash.jpg" type="image/jpeg" />
      <category>posts, CFML, ColdFusion, Lucee</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>Connection pools in Node.js with MariaDB</title>
      <link>https://www.andyjarrett.com/posts/2024/connection-pools-in-node-with-mariadb/</link>
      <description><![CDATA[
&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/alec-weir-I1vgh8AJr94-unsplash.jpg&quot; alt=&quot;MariaDB optimisation&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;Photo by &lt;a href=&quot;https://unsplash.com/@xcvii?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Alec Weir&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/brown-walrus-in-rule-of-thirds-photography-I1vgh8AJr94?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Find the GitHub project here: &lt;a rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/andyj/mariadb-connection-pool&quot;&gt;github.com/andyj/mariadb-connection-pool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;Why Use a Connection Pool?&lt;/h2&gt;

&lt;p&gt;Database connection pooling critical for your web applications. Without a pool, every database query spins up a new connection which startes eating up your resources! A connection pool keeps a stash of open connections ready to go, slashing overhead and boosting performance.&lt;/p&gt;

&lt;p&gt;This also gave me an excuse to go back over some old code of mine and start putting in &lt;a href=&quot;https://www.andyjarrett.com/posts/2024/utility-console-methods-for-debugging-workflow/&quot; title=&quot;Utility Console Methods For Debugging Your Javascript Workflow&quot;&gt;console methods for debugging&lt;/a&gt; that I&#39;ve covered &lt;a href=&quot;https://www.andyjarrett.com/posts/2024/advanced-javascript-console-methods/&quot; title=&quot;Advanced Javascript Console Techniques Every Developer Should Be Aware Of&quot;&gt;recently&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Benefits of Connection Pooling&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Reduced latency:&lt;/strong&gt; Reusing connections cuts out the time spent establishing new ones.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Better resource management:&lt;/strong&gt; Caps the number of simultaneous connections to keep your database happy.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Improved scalability:&lt;/strong&gt; Handle more users without breaking a sweat.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Setting Up a MariaDB Connection Pool in Node.js&lt;/h3&gt;

&lt;p&gt;First things first, you&#39;ll need the &lt;code&gt;mariadb&lt;/code&gt; package. Install it using:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install mariadb dotenv&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here&#39;s how to set up the pool:&lt;/p&gt;

&lt;h4&gt;Connection Pool Configuration&lt;/h4&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;
// db.js
require(&#39;dotenv&#39;).config(); // Load environment variables

const mariadb = require(&#39;mariadb&#39;);

const pool = mariadb.createPool({
  host: process.env.DB_HOST,         // Use DB_HOST environment variable from .env
  user: process.env.DB_USER,         // Use DB_USER environment variable from .env
  password: process.env.DB_PASSWORD, // Use DB_PASSWORD environment variable from .env
  database: process.env.DB_NAME,     // Use DB_NAME environment variable from .env
  port: process.env.DB_PORT,         // Use DB_PORT environment variable from .env
  connectionLimit: 10                // Maximum number of connections in the pool
});

module.exports = pool;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This creates a pool with up to 10 connections. Feel free to tweak the &lt;code&gt;connectionLimit&lt;/code&gt; based on what your app needs.&lt;/p&gt;

&lt;h3&gt;Using the Pool in Your Application&lt;/h3&gt;

&lt;p&gt;Let&#39;s look at how to use the connection pool in an Express route. We&#39;ll sprinkle in some advanced console methods to make debugging a breeze.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;
const express = require(&#39;express&#39;);
const pool = require(&#39;./db&#39;); // Import the pool
const app = express();

app.get(&#39;/data&#39;, async (req, res) =&gt; {
  console.group(&#39;Database Query&#39;);
  console.time(&#39;Query Time&#39;);

  let conn;
  try {
    conn = await pool.getConnection();
    console.assert(conn, &#39;Failed to obtain a database connection&#39;);

    const rows = await conn.query(&#39;SELECT current_timestamp()&#39;);
    console.table(rows);

    res.json(rows);
  } catch (err) {
    console.error(&#39;Error executing query&#39;);
    console.trace(err);
    res.status(500).send(&#39;Database query error&#39;);
  } finally {
    if (conn) conn.release(); // Release the connection back to the pool
    console.timeEnd(&#39;Query Time&#39;);
    console.groupEnd();
  }
});

app.listen(3000, () =&gt; {
  console.log(&#39;Server is running on port 3000&#39;);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here&#39;s what those console methods are doing for you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;console.group()&lt;/code&gt; and &lt;code&gt;console.groupEnd()&lt;/code&gt;: Groups related log messages, making your console output neater.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;console.time()&lt;/code&gt; and &lt;code&gt;console.timeEnd()&lt;/code&gt;: Measures how long your query takes, helping you spot performance issues.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;console.assert()&lt;/code&gt;: Checks if you got a connection. If not, it logs an error message.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;console.table()&lt;/code&gt;: Displays your query results in a nice table format in the console.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;console.trace()&lt;/code&gt;: Prints a stack trace from the point where it&#39;s called, super handy for debugging errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using these methods, you get a clearer picture of what&#39;s going on under the hood, which is clutch when you&#39;re trying to debug or optimize your app.&lt;/p&gt;

&lt;h3&gt;Best Practices&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;Keep an eye on pool usage to tweak &lt;code&gt;connectionLimit&lt;/code&gt; as needed.&lt;/li&gt;
  &lt;li&gt;Use connection timeouts to handle idle or long-running queries.&lt;/li&gt;
  &lt;li&gt;Implement error handling to gracefully manage database hiccups.&lt;/li&gt;
  &lt;li&gt;Leverage advanced console methods to make debugging smoother.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;The mariadb package makes it easy to manage database connections efficiently.&lt;/p&gt;

&lt;p&gt;And if you’re using managed database services like AWS RDS for MariaDB or Azure Database for MariaDB, there are additional settings you should consider tweaking for optimal performance:&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;&lt;strong&gt;Connection Pool Limits&lt;/strong&gt;: AWS and Azure instances often come with predefined limits on concurrent connections based on the instance size. Make sure your connectionLimit aligns with these constraints to avoid hitting caps that could cause connection errors.&lt;/li&gt;
   &lt;li&gt;&lt;strong&gt;Timeouts and Idle Connections&lt;/strong&gt;: Both AWS and Azure charge for resources tied to active connections. Use settings like idleTimeoutMillis to close unused connections after a certain period. This helps in reducing costs and freeing up database resources.&lt;/li&gt;
   &lt;li&gt;&lt;strong&gt;Max Allowed Packet&lt;/strong&gt;: Tweak this for handling large queries or data sets, especially if your app processes bulk data.&lt;/li&gt;
   &lt;li&gt;&lt;strong&gt;Monitoring and Scaling&lt;/strong&gt;: Both platforms offer native monitoring tools (e.g., Amazon CloudWatch or Azure Monitor) to keep an eye on metrics like CPU usage, connections, and query performance. Use these insights to adjust your pool size dynamically.&lt;/li&gt;
&lt;/ul&gt;

]]></description>
      <pubDate>Tue, 19 Nov 2024 07:30:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2024/connection-pools-in-node-with-mariadb/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/alec-weir-I1vgh8AJr94-unsplash.jpg" type="image/jpeg" />
      <category>posts</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>How to Run SVR.JS with Docker Compose</title>
      <link>https://www.andyjarrett.com/posts/2024/how-to-run-svrjs-with-docker-compose/</link>
      <description><![CDATA[
&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/florian-olivo-4hbJ-eymZ1o-unsplash.jpg&quot; alt=&quot;Man running towards mountains&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;
      Photo by &lt;a rel=&quot;noopener noreferrer&quot; href=&quot;https://unsplash.com/@florianolv?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Florian Olivo&lt;/a&gt; on &lt;a rel=&quot;noopener noreferrer&quot; href=&quot;https://unsplash.com/photos/lines-of-html-codes-4hbJ-eymZ1o?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;
    &lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;



&lt;p&gt;
  &lt;strong&gt;TL;DR:&lt;/strong&gt;
  Project code here: &lt;a href=&quot;https://github.com/andyj/svrjs-with-docker&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot;&gt;github.com/andyj/svrjs-with-docker&lt;/a&gt;
&lt;/p&gt;


&lt;h1&gt;Why SVR.JS?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://svrjs.org/&quot; rel=&quot;noopener noreferrer&quot;&gt;SVR.JS&lt;/a&gt; is a lightweight and efficient web server designed to serve static files effortlessly. It&#39;s great for scenarios where you need a quick and reliable solution to host static content without the overhead of traditional web servers. &lt;/p&gt;
&lt;p&gt;By combining SVR.JS with Docker, you can eliminate installation dependencies and simplify deployment, making it an ideal choice for developers, testers, and small-scale projects.&lt;/p&gt;

&lt;h2&gt;How to Set It Up&lt;/h2&gt;


&lt;h3&gt;Step 1: Docker Compose Configuration&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;version: &#39;3.9&#39;
services:
  svrjs:
    image: svrjs/svrjs:lts
    container_name: svrjs-server
    platform: linux/amd64
    ports:
      - &quot;8080:80&quot;  # Map port 8080 on host to port 80 in the container
    volumes:
      - ./www:/var/www/svrjs  # Mount the local `www` directory as the web root
      - ./svrjs-config.json:/etc/svrjs-config.json  # Mount custom config
    restart: always
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This &lt;code&gt;docker-compose.yml&lt;/code&gt; file defines the SVR.JS service. It maps port 8080 on the host to port 80 in the container and sets up volumes for the web root and configuration file.&lt;/p&gt;

&lt;h3&gt;Step 2: Configuration File&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;port&quot;: 80,
  &quot;wwwroot&quot;: &quot;/var/www/svrjs&quot;,
  &quot;logging&quot;: {
    &quot;enabled&quot;: true,
    &quot;level&quot;: &quot;info&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Save this as &lt;code&gt;svrjs-config.json&lt;/code&gt;. It configures SVR.JS to serve files from the specified directory and enables basic logging.&lt;/p&gt;

&lt;h3&gt;Step 3: Directory Structure&lt;/h3&gt;
&lt;p&gt;Create the following directory structure for your project:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;svrjs-with-docker
├── README.md
├── docker-compose.yml
├── svrjs-config.json
└── www
    ├── index.html
    └── style.css
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;www&lt;/code&gt; folder will hold your static files, such as &lt;code&gt;index.html&lt;/code&gt; and &lt;code&gt;style.css&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;Step 4: Example HTML File&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
  &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
  &amp;lt;title&amp;gt;SVR.JS Test&amp;lt;/title&amp;gt;
  &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Welcome to SVR.JS&amp;lt;/h1&amp;gt;
  &amp;lt;p&amp;gt;This static file is served by SVR.JS.&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Save this as &lt;code&gt;index.html&lt;/code&gt; inside the &lt;code&gt;www&lt;/code&gt; directory.&lt;/p&gt;

&lt;h3&gt;Step 5: Running the Server&lt;/h3&gt;
&lt;p&gt;In the root directory of your project, run the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker-compose up&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After the container starts, visit &lt;a href=&quot;http://localhost:8080/&quot; target=&quot;_blank&quot;&gt;http://localhost:8080&lt;/a&gt; to see your static site in action.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;SVR.JS, combined with Docker, provides a powerful and hassle-free way to serve static content. This setup is highly portable and easy to replicate across different environments, making it a valuable tool for developers of all levels.&lt;/p&gt;



]]></description>
      <pubDate>Tue, 26 Nov 2024 22:30:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2024/how-to-run-svrjs-with-docker-compose/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/florian-olivo-4hbJ-eymZ1o-unsplash.jpg" type="image/jpeg" />
      <category>posts, docker, svrjs, tutorial</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>Using SVR.js to Run Server-Side JavaScript</title>
      <link>https://www.andyjarrett.com/posts/2024/using-svr-js-to-run-server-side-javascript/</link>
      <description><![CDATA[

&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/photo-of-outer-space.jpeg&quot; alt=&quot;Nasa Space Photo&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;Photo by &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://unsplash.com/@nasa?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;NASA&lt;/a&gt; on &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://unsplash.com/photos/photo-of-outer-space-Q1p7bh3SHj8?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Updated project code here: &lt;a rel=&quot;noopener noreferrer&quot; href=&quot;https://github.com/andyj/svrjs-with-docker&quot; target=&quot;_blank&quot;&gt;github.com/andyj/svrjs-with-docker&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;How to Use SVR.js to Run Server-Side JavaScript&lt;/h1&gt;

&lt;h2&gt;Building on the Basics&lt;/h2&gt;
&lt;p&gt;In my previous post, &lt;a href=&quot;https://www.andyjarrett.com/posts/2024/how-to-run-svrjs-with-docker-compose/&quot;&gt;How to Run SVR.js with Docker Compose&lt;/a&gt;, I introduced a simple way to set up SVR.js for serving static files using Docker Compose. Since then, I’ve expanded the project to explore server-side capabilities of SVR.js.&lt;/p&gt;
&lt;p&gt;To accommodate this, the project structure has evolved on GitHub, and now includes multiple folders for different setups. Specifically, the new &lt;code&gt;2.serverside-javascript-svrjs&lt;/code&gt; folder demonstrates how to run server-side JavaScript. Let’s dive in!&lt;/p&gt;

&lt;h2&gt;Updated Project Structure&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;svrjs-with-docker/
├── 1. how-to-run-svrjs-with-docker-compose
│   ├── README.md
│   ├── docker-compose.yml
│   ├── svrjs-config.json
│   └── www
│       ├── index.html
│       └── style.css
├── 2.serverside-javascript-svrjs
│   ├── README.md
│   ├── docker-compose.yml
│   ├── server
│   │   └── time.js
│   ├── svrjs-config.json
│   └── www
│       ├── index.html
│       └── style.css
├── LICENSE
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Step 1: The Configuration File&lt;/h2&gt;
&lt;p&gt;The new &lt;code&gt;svrjs-config.json&lt;/code&gt; enables server-side JavaScript by defining a route that maps to a server-side script:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
&quot;port&quot;: 80,
&quot;wwwroot&quot;: &quot;/var/www/svrjs&quot;,
&quot;logging&quot;: {
  &quot;enabled&quot;: true,
  &quot;level&quot;: &quot;info&quot;
},
&quot;routes&quot;: {
  &quot;/time&quot;: &quot;../server/time.js&quot;
}
}&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Step 2: Writing Server-Side Logic&lt;/h2&gt;
&lt;p&gt;Create the &lt;code&gt;time.js&lt;/code&gt; file in the &lt;code&gt;server&lt;/code&gt; folder:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;module.exports = (req, res) =&gt; {
  const currentTime = new Date().toLocaleString();
  res.setHeader(&#39;Content-Type&#39;, &#39;application/json&#39;);
  res.end(JSON.stringify({ message: &quot;Hello, World!&quot;, time: currentTime }));
};&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Step 3: Updated Docker Compose Configuration&lt;/h2&gt;
&lt;p&gt;Here’s the &lt;code&gt;docker-compose.yml&lt;/code&gt; file for this setup:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;services:
svrjs:
  image: svrjs/svrjs:lts
  container_name: svrjs-server
  platform: linux/amd64
  ports:
    - &quot;8282:80&quot;
  volumes:
    - ./www:/var/www/svrjs
    - ./server:/var/server
    - ./svrjs-config.json:/etc/svrjs-config.json
  restart: always&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Step 4: Running the Server&lt;/h2&gt;
&lt;p&gt;Run the following command from the &lt;code&gt;2.serverside-javascript-svrjs&lt;/code&gt; directory:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker compose up&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once the container is running, navigate to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Static Files:&lt;/strong&gt; &lt;a href=&quot;http://localhost:8282/&quot; target=&quot;_blank&quot;&gt;http://localhost:8282&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Server-Side Endpoint:&lt;/strong&gt; &lt;a href=&quot;http://localhost:8282/time&quot; target=&quot;_blank&quot;&gt;http://localhost:8282/time&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Testing the Endpoint&lt;/h2&gt;
&lt;p&gt;Visiting &lt;code&gt;/time&lt;/code&gt; in your browser or via a tool like &lt;code&gt;curl&lt;/code&gt; will return a JSON response similar to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
&quot;message&quot;: &quot;Hello, World!&quot;,
&quot;time&quot;: &quot;28/11/2024, 15:00:00&quot;
}&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;With minimal effort, SVR.js transforms from a static file server into a lightweight tool for handling server-side JavaScript. By leveraging Docker for deployment, this setup is both portable and scalable.&lt;/p&gt;
&lt;p&gt;What server-side features will you build next with SVR.js? Let me know in the comments or contribute to the project on &lt;a href=&quot;https://github.com/andyj/svrjs-with-docker&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;!&lt;/p&gt;
]]></description>
      <pubDate>Fri, 29 Nov 2024 22:30:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2024/using-svr-js-to-run-server-side-javascript/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/photo-of-outer-space.jpeg" type="image/jpeg" />
      <category>posts, docker, svrjs, tutorial</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>Why Updating Alpine.js State with Direct Reassignment Fails (and How to Fix It)</title>
      <link>https://www.andyjarrett.com/posts/2025/why-updating-alpinejs-state-with-direct-reassignme/</link>
      <description><![CDATA[


&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/trevor-wilson--8uTE4FWxkU-unsplash.jpg&quot; alt=&quot;Green mountain under blue sky&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;Photo by &lt;a href=&quot;https://unsplash.com/@clevertrevor?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Trevor Wilson&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/trees-covered-mountains-during-daytime--8uTE4FWxkU?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;
&lt;div class=&quot;container my-5&quot;&gt;
  &lt;h1 class=&quot;mb-4&quot;&gt;Why Updating Alpine.js State with Direct Reassignment Fails (and How to Fix It)&lt;/h1&gt;

  &lt;p&gt;Reactivity is amazing, but when it fails its frustrating. And with that a stupid issue hit me recently because of direct reassignment of a variable that I did. In my defence I was reassigning the property  &lt;code&gt;this.formFields&lt;/code&gt; after fetching JSON. So, this blog post is here to remind me to check the obvious first.&lt;/p&gt;

  &lt;hr class=&quot;my-4&quot; /&gt;

  &lt;p&gt;I&#39;m going to use &lt;a href=&quot;https://dummyjson.com/&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot;&gt;dummyjson.com&lt;/a&gt; to get some data to explain. Imagine you’re building a product page, and you want to fetch product details from an API and update your form fields dynamically. Here’s a simplified HTML:&lt;/p&gt;

  &lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div x-data=&quot;productForm()&quot; x-init=&quot;fetchProduct()&quot;&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;p&amp;gt;Title: &amp;lt;span x-text=&quot;formFields.title&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Price: &amp;pound;&amp;lt;span x-text=&quot;formFields.price&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Rating: &amp;lt;span x-text=&quot;formFields.rating&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Stock: &amp;lt;span x-text=&quot;formFields.stock&quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And Alpine.js component&lt;/p&gt;

  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function productForm() {
  return {
    formFields: {
      title: &#39;&#39;,
      price: 0,
      rating: 0,
      stock: 0
    },
    async fetchProduct() {
      const response = await fetch(&#39;https://dummyjson.com/products/1&#39;);
      const json = await response.json();

      // Replace formFields but rebind to Alpine
      this.formFields = json;
    }
  };
}&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;The API response:&lt;/p&gt;

  &lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;id&quot;: 1,
  &quot;title&quot;: &quot;Essence Mascara Lash Princess&quot;,
  &quot;price&quot;: 9.99,
  &quot;rating&quot;: 4.94,
  &quot;stock&quot;: 5
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;The result:&lt;/strong&gt; The values have not changed, and still showing the default values.&lt;/p&gt;


  &lt;h2&gt;Why This Fails&lt;/h2&gt;
  &lt;p&gt;When you reassign &lt;code&gt;this.formFields&lt;/code&gt; to the new &lt;code&gt;json&lt;/code&gt; object, Alpine.js no longer tracks changes to &lt;code&gt;formFields&lt;/code&gt;. This is because Alpine’s reactivity system is based on proxies, and direct reassignment breaks the connection to the original proxy object.&lt;/p&gt;

  &lt;p&gt;In essence, Alpine.js is still observing the old &lt;code&gt;formFields&lt;/code&gt; object, but you’ve replaced it with a completely new object.&lt;/p&gt;

  &lt;h2&gt;The Fix&lt;/h2&gt;
  &lt;p&gt;Instead of directly reassigning the object, update individual properties of &lt;code&gt;formFields&lt;/code&gt; so that Alpine’s reactivity remains intact:&lt;/p&gt;

  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;async fetchProduct() {
  const response = await fetch(&#39;https://dummyjson.com/products/1&#39;);
  const json = await response.json();

  // Update individual properties
  this.formFields.title = json.title;
  this.formFields.price = json.price;
  this.formFields.rating = json.rating;
  this.formFields.stock = json.stock;
}&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;By updating the properties one by one, Alpine.js can detect and respond to the changes properly.&lt;/p&gt;

  &lt;h2&gt;A Cleaner Approach&lt;/h2&gt;
  &lt;p&gt;If you’re working with multiple properties, you can use &lt;code&gt;Object.assign&lt;/code&gt; to merge the new data into the existing &lt;code&gt;formFields&lt;/code&gt; object:&lt;/p&gt;

  &lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;async fetchProduct() {
  const response = await fetch(&#39;https://dummyjson.com/products/1&#39;);
  const json = await response.json();

  // Merge new data into formFields
  Object.assign(this.formFields, {
    title: json.title,
    price: json.price,
    rating: json.rating,
    stock: json.stock
  });

  // Or you could do this
  // Object.assign(this.formFields, json);
  // though if the json object contains additional properties that you don’t want in this.formFields, they will also be added.
}&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;This approach avoids keeps the code clean and maintainable.&lt;/p&gt;

  &lt;hr class=&quot;my-4&quot; /&gt;
  &lt;p&gt;Direct reassignment of an object in Alpine.js may seem intuitive, but it can break the reactivity system. By updating individual properties or merging data using &lt;code&gt;Object.assign&lt;/code&gt;, you can ensure your state remains reactive and your UI updates as expected. This small adjustment can save you significant debugging time and (for me) frustration in Alpine.js projects.&lt;/p&gt;
&lt;/div&gt;
]]></description>
      <pubDate>Fri, 10 Jan 2025 17:30:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2025/why-updating-alpinejs-state-with-direct-reassignme/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/trevor-wilson--8uTE4FWxkU-unsplash.jpg" type="image/jpeg" />
      <category>posts, alpinejs, javascript, web development, reactivity, html</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>Fixing Alpine.js Template Rendering Issues When Your Second Tag Isn&#39;t Showing</title>
      <link>https://www.andyjarrett.com/posts/2025/fixing-alpinejs-template-rendering-issues-when-your-second-tag-isnt-showing/</link>
      <description><![CDATA[
&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/ales-krivec-7wQsXq_HKJo-unsplash.jpg&quot; alt=&quot;&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;Photo by &lt;a href=&quot;https://unsplash.com/@aleskrivec?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Ales Krivec&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/fern-tree-under-white-clouds-7wQsXq_HKJo?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;

&lt;p&gt;When working with Alpine.js templates, I ran into an issue where only the first child element inside a &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag is rendered, leaving subsequent elements mysteriously absent.&lt;/p&gt;

&lt;h2&gt;Understanding the Problem&lt;/h2&gt;
&lt;p&gt;Consider the following code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template x-if=&quot;products.product_id&quot;&amp;gt;
  &amp;lt;a :href=&quot;`/products/edit/${products.item_short_ref}/${products.item_code}`&quot; class=&quot;px-2&quot;&amp;gt;
    Edit
  &amp;lt;/a&amp;gt;
  &amp;lt;a :href=&quot;`/products/delete/${products.item_short_ref}/${products.item_code}`&quot; class=&quot;px-2&quot;&amp;gt;
    Delete
  &amp;lt;/a&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might expect both &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags to render when the &lt;code&gt;x-if&lt;/code&gt; condition is true. However, Alpine.js requires a single root element inside the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag. If there are multiple sibling elements, only the first one will appear.&lt;/p&gt;

&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;To resolve this, wrap the content inside the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; in a parent container, such as a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;. Here’s the corrected code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;template x-if=&quot;products.product_id&quot;&amp;gt;
  &amp;lt;span class=&quot;flex&quot;&amp;gt;
    &amp;lt;a :href=&quot;`/products/edit/${products.item_short_ref}/${products.item_code}`&quot; class=&quot;px-2&quot;&amp;gt;
      Edit
    &amp;lt;/a&amp;gt;
    &amp;lt;a :href=&quot;`/products/delete/${products.item_short_ref}/${products.item_code}`&quot; class=&quot;px-2&quot;&amp;gt;
      Delete
    &amp;lt;/a&amp;gt;
  &amp;lt;/span&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; acts as the single root node required by Alpine.js, allowing both &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags to render properly.&lt;/p&gt;

&lt;h2&gt;A Demo of the Issue and Solution&lt;/h2&gt;
&lt;p&gt;Here’s a simplified demonstration to illustrate the problem:&lt;/p&gt;

&lt;h3&gt;Code with Issue&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div x-data=&quot;{ open: false }&quot;&amp;gt;
  &amp;lt;button x-on:click=&quot;open = !open&quot;&amp;gt;Toggle 1 (shows one link only)&amp;lt;/button&amp;gt;
  &amp;lt;template x-if=&quot;open&quot;&amp;gt;
    &amp;lt;a href=&quot;#&quot;&amp;gt;Link 1&amp;lt;/a&amp;gt;
    &amp;lt;a href=&quot;#&quot;&amp;gt;Link 2&amp;lt;/a&amp;gt;
  &amp;lt;/template&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case, only &quot;Link 1&quot; will appear when you click the button.&lt;/p&gt;

&lt;h3&gt;Corrected Code&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div x-data=&quot;{ open: false }&quot;&amp;gt;
  &amp;lt;button x-on:click=&quot;open = !open&quot;&amp;gt;Toggle 2 (shows both links)&amp;lt;/button&amp;gt;
  &amp;lt;template x-if=&quot;open&quot;&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;a href=&quot;#&quot;&amp;gt;Link 1&amp;lt;/a&amp;gt;
      &amp;lt;a href=&quot;#&quot;&amp;gt;Link 2&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/template&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, both links will render correctly when the button is toggled.&lt;/p&gt;

]]></description>
      <pubDate>Mon, 13 Jan 2025 23:28:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2025/fixing-alpinejs-template-rendering-issues-when-your-second-tag-isnt-showing/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/ales-krivec-7wQsXq_HKJo-unsplash.jpg" type="image/jpeg" />
      <category>posts, javascript, alpinejs, templates, frontend, web development</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>Provisioning OneDrive for Microsoft365 Users Before First Login</title>
      <link>https://www.andyjarrett.com/posts/2025/provisioning-onedrive-for-microsoft-365-users-before-first-login/</link>
      <description><![CDATA[
&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/appshunter-io-aFDdAddufcY-unsplash.jpg&quot; alt=&quot;OneDrive Automation&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;Photo by &lt;a href=&quot;https://unsplash.com/@appshunter?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;appshunter.io&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/a-close-up-of-a-cell-phone-on-a-table-aFDdAddufcY?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;

&lt;h2&gt;Why Pre-Provision OneDrive?&lt;/h2&gt;
&lt;p&gt;By default, OneDrive accounts for Microsoft 365 users are not created until they sign in for the first time. However, if you’re planning a migration from another cloud provider, such as Google Drive, you need to provision these OneDrive accounts in advance to ensure a smooth transition as we found out.&lt;/p&gt;

&lt;p&gt;Below is a rough guide and &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://learn.microsoft.com/en-us/powershell/sharepoint/&quot;&gt;SharePoint PowerShell&lt;/a&gt; script to automate the process.&lt;/p&gt;

&lt;h2&gt;Pre-Requisites&lt;/h2&gt;
&lt;p&gt;Before running the script, you need to ensure that PowerShell allows execution of scripts. Run the following command in PowerShell (this cannot be part of the script itself):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This enables execution for the session without changing system-wide policies.&lt;/p&gt;

&lt;h2&gt;The PowerShell Script&lt;/h2&gt;
&lt;p&gt;Save the following script as &lt;code&gt;provision_onedrive.ps1&lt;/code&gt;. It connects to your SharePoint Online admin centre and checks whether OneDrive is provisioned for each user. If not, it requests its creation.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Define the list of user emails
$UserEmails = @(
&quot;firstname1.lastname1@example.com&quot;,
&quot;firstname2.lastname2@example.com&quot;,
&quot;firstname3.lastname3@example.com&quot;
)

# Define SharePoint Online Admin URL (replace with your actual tenant)
$TenantAdminURL = &quot;https://[your-tenant]-admin.sharepoint.com&quot;

# Connect to SharePoint Online (if not already connected)
Try {
    Connect-SPOService -Url $TenantAdminURL -ErrorAction Stop
    Write-Host &quot;Connected to SharePoint Online successfully.&quot;
} Catch {
    Write-Host &quot;Error connecting to SharePoint Online: $_&quot; -ForegroundColor Red
    Exit
}

# Loop through each user email
foreach ($email in $UserEmails) {
    Write-Host &quot;Checking OneDrive status for $email...&quot;

    # Check if OneDrive is already provisioned
    $site = Get-SPOSite -IncludePersonalSite $true -Limit all | Where-Object { $_.Owner -eq $email } -ErrorAction SilentlyContinue

    if ($site) {
        Write-Host &quot;OneDrive already exists for $email&quot; -ForegroundColor Green
    } else {
        Write-Host &quot;Provisioning OneDrive for $email...&quot; -ForegroundColor Yellow
        Request-SPOPersonalSite -UserEmails $email
        Write-Host &quot;OneDrive provisioning requested for $email&quot; -ForegroundColor Cyan
    }
}

Write-Host &quot;OneDrive provisioning script completed.&quot; -ForegroundColor Magenta&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;How It Works&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;The script defines a list of user emails.&lt;/li&gt;
  &lt;li&gt;It connects to the SharePoint Online admin centre.&lt;/li&gt;
  &lt;li&gt;It checks if OneDrive is already provisioned for each user.&lt;/li&gt;
  &lt;li&gt;If OneDrive is missing, it requests its creation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Running the Script&lt;/h2&gt;
&lt;p&gt;To execute the script, open PowerShell as an administrator and run:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;.&#92;provision_onedrive.ps1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&#39;ll see output indicating whether each user&#39;s OneDrive already exists or has been requested for provisioning.&lt;/p&gt;

&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Pre-provisioning OneDrive ensures a seamless migration for users switching from Google Drive or other storage solutions. This automation removes delays and guarantees that user drives are ready before they even log in.&lt;/p&gt;

&lt;p&gt;Let me know in the comments if you have any questions or if you’d like additional automation enhancements!&lt;/p&gt;
]]></description>
      <pubDate>Tue, 04 Feb 2025 00:00:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2025/provisioning-onedrive-for-microsoft-365-users-before-first-login/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/appshunter-io-aFDdAddufcY-unsplash.jpg" type="image/jpeg" />
      <category>posts, PowerShell, OneDrive, Microsoft 365, Automation</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <item>
      <title>Learning Python Offline with a PWA</title>
      <link>https://www.andyjarrett.com/posts/2025/learning_python_offline_with_a_pwa/</link>
      <description><![CDATA[
&lt;div class=&quot;image-container my-2&quot;&gt;
  &lt;img src=&quot;https://www.andyjarrett.com/public/blogimage/rubaitul-azad-ZIPFteu-R8k-unsplash.jpg&quot; alt=&quot;Offline Python PWA Screenshot&quot; class=&quot;img-fluid&quot; /&gt;
&lt;/div&gt;
&lt;div class=&quot;text-end&quot;&gt;
  &lt;sup&gt;
    &lt;cite&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rubaitulazad?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Rubaitul Azad&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/photos/a-white-cube-with-a-yellow-and-blue-logo-on-it-ZIPFteu-R8k?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&quot;&gt;Unsplash&lt;/a&gt;&lt;/cite&gt;
  &lt;/sup&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Explore the offline Python PWA on GitHub: &lt;a href=&quot;https://github.com/andyj/learn_python_offline_pwa&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;github.com/andyj/learn_python_offline_pwa&lt;/a&gt; and &lt;a href=&quot;https://andyj.github.io/learn_python_offline_pwa/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;View The App Here&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Learning Python Offline with a PWA&lt;/h1&gt;

&lt;h2&gt;Why AI, Why Offline?&lt;/h2&gt;
&lt;p&gt;I’ve always wanted to get back to basics and truly understand Python’s core concepts without being tethered to a network. When my family and I started planning a trip I realised I’d be offline for a bit and I saw an opportunity. Why not build a Progressive Web App (PWA) that teaches Python fundamentals entirely client-side, even when you’ve got zero signal?&lt;/p&gt;

&lt;h2&gt;Building Skulpt Locally&lt;/h2&gt;
&lt;p&gt;Rather than pulling Skulpt from a CDN, I cloned the public repositories, ran the build process locally (with a quick &lt;code&gt;nvm&lt;/code&gt; switch to Node 16 to avoid OpenSSL issues), and bundled the minified &lt;code&gt;skulpt.min.js&lt;/code&gt; and &lt;code&gt;skulpt-stdlib.js&lt;/code&gt; into &lt;code&gt;dist/&lt;/code&gt;. That way the entire runtime ships with the app—no internet required.&lt;/p&gt;

&lt;h2&gt;Technical Highlights&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Offline-first:&lt;/strong&gt; A service worker precaches every HTML, CSS, JS and Skulpt asset.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Single page layout:&lt;/strong&gt; Collapsible sidebar for navigation; main pane for lessons, code editors and quizzes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Interactive code:&lt;/strong&gt; Editable Python snippets powered by Skulpt, with real-time output.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Progress tracking:&lt;/strong&gt; Quiz results saved in &lt;code&gt;localStorage&lt;/code&gt;, so you can pick up where you left off.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Lightweight styling:&lt;/strong&gt; Mobile-first, plain CSS, no frameworks, so it’s lightning fast and fully functional offline.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Try It Yourself&lt;/h2&gt;
&lt;p&gt;You can explore the code, clone the repo, or file issues over on GitHub:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/andyj/learn_python_offline_pwa&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;🔗 https://github.com/andyj/learn_python_offline_pwa&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Whether you’re a digital nomad, a commuter or just someone who likes to tinker offline, this PWA lets you learn Python wherever you are. Give it a spin on your device, just add it to your home screen and you’re good to go.&lt;/p&gt;
]]></description>
      <pubDate>Sat, 17 May 2025 07:01:00 +0000</pubDate>
      <dc:creator>Andy Jarrett</dc:creator>
      <guid>https://www.andyjarrett.com/posts/2025/learning_python_offline_with_a_pwa/</guid>
      <enclosure url="https://www.andyjarrett.com/public/blogimage/rubaitul-azad-ZIPFteu-R8k-unsplash.jpg" type="image/jpeg" />
      <category>posts, python, pwa, offline, skulpt, tutorial</category>
      <author>Andy Jarrett &lt;email@example.com&gt;</author>
    </item>
    <image>
      <url>https://www.andyjarrett.com/public/img/Andy-Jarrett.com.png</url>
      <title>Andy Jarrett. Code. Develop. Create.</title>
      <link>https://www.andyjarrett.com/</link>
    </image>
  </channel>
</rss>
