<?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: Richard Zampieri</title>
    <description>The latest articles on DEV Community by Richard Zampieri (@rsaz).</description>
    <link>https://dev.to/rsaz</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%2F469391%2F39858aa0-a6ba-43ff-ac7a-7492ad74c9da.jpeg</url>
      <title>DEV Community: Richard Zampieri</title>
      <link>https://dev.to/rsaz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rsaz"/>
    <language>en</language>
    <item>
      <title>Web/Mobile Personal AI CFO</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Sat, 21 Feb 2026 10:00:50 +0000</pubDate>
      <link>https://dev.to/rsaz/webmobile-personal-ai-cfo-2k81</link>
      <guid>https://dev.to/rsaz/webmobile-personal-ai-cfo-2k81</guid>
      <description>&lt;h2&gt;
  
  
  How I Built an AI-Powered Finance App and distributed it's services to support volume and concurrency
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.fintrackai.app" rel="noopener noreferrer"&gt;FinTrack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A technical high level walkthrough of building a personal finance application that combines traditional CRUD with AI features—and why I split the services&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I wanted to build a personal finance app that could do more than track transactions. I wanted it to &lt;em&gt;understand&lt;/em&gt; your finances: answer questions in natural language, categorize expenses automatically, and even take voice input, like a real personal assistant, so users dont have to type everything, you can ask Finny. The challenge? Most AI work happens in Python, while typical web backends live in Node.js. How do you get the best of both worlds without a tangled mess?&lt;/p&gt;

&lt;p&gt;This is how I did it.&lt;br&gt;
Obs: remember that are more than one way to skin the cat and all comes down to concurrency, volume, cost, context in which your app will start running.&lt;/p&gt;




&lt;h2&gt;
  
  
  High-Level Architecture
&lt;/h2&gt;

&lt;p&gt;I chose a &lt;strong&gt;dual-backend architecture&lt;/strong&gt;: one service for the core application, another dedicated entirely to AI. Here's the flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadz550skrd8hm2bjehuk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadz550skrd8hm2bjehuk.png" alt="High level arch" width="794" height="886"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend:&lt;/strong&gt; React with TypeScript and Vite. Pages, components, contexts, and hooks all feed into a single API abstraction layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ExpressoTS API:&lt;/strong&gt; Handles all non-AI operations—transactions, accounts, goals, budgets, auth. We use &lt;a href="https://expresso-ts.com/" rel="noopener noreferrer"&gt;ExpressoTS&lt;/a&gt;—a type-safe TypeScript framework I created about five years ago for building scalable Node.js APIs. Database used Postgres.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python AI Service:&lt;/strong&gt; A separate service for &lt;em&gt;everything&lt;/em&gt; AI: RAG (retrieval-augmented generation) for chat, transaction classification, voice transcript parsing, and document extraction. It calls out to an LLM provider for embeddings and completions. Good tip here is OpenRouter!&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Split the Backend?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Keep API Keys Server-Side
&lt;/h3&gt;

&lt;p&gt;AI providers require API keys. We never expose them in the frontend. All AI requests flow through our Python service, which holds the credentials and proxies requests. The browser never talks to the AI provider directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Python's Strengths for AI
&lt;/h3&gt;

&lt;p&gt;Transaction classification, embeddings, RAG pipelines—these are natural fits for Python. The ecosystem (NumPy, pandas, OpenAI SDK, etc.) is mature. Trying to replicate that in Node would mean more custom code and more maintenance.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Independent Scaling and Concurrency
&lt;/h3&gt;

&lt;p&gt;CRUD traffic and AI traffic have different profiles. With two services, we can scale each independently. A spike in chat usage doesn't affect the core transaction APIs. The ExpressoTS API handles many concurrent requests efficiently—it's built for speed with minimal overhead—while the Python service processes AI workloads in isolated batches. That separation means we're not blocking CRUD requests while classification jobs run, and vice versa.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Clear Separation of Concerns
&lt;/h3&gt;

&lt;p&gt;Developers know exactly where logic lives: business data and CRUD in ExpressoTS, AI and ML in Python. That separation makes onboarding and refactoring much easier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frontend Structure
&lt;/h2&gt;

&lt;p&gt;The app follows a clean layering pattern:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;UI&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;components/&lt;/code&gt;, &lt;code&gt;pages/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Presentational components only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;contexts/&lt;/code&gt;, &lt;code&gt;hooks/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Global state and reusable logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;&lt;code&gt;api/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All data-fetching and API calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Utils&lt;/td&gt;
&lt;td&gt;&lt;code&gt;utils/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pure functions, no side effects&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;api/&lt;/code&gt; folder is the single entry point for backend communication. It doesn't care whether a request goes to ExpressoTS or Python—it just exposes functions like &lt;code&gt;fetchTransactions()&lt;/code&gt;, &lt;code&gt;classifyTransactions()&lt;/code&gt;, or &lt;code&gt;askFinny()&lt;/code&gt;. The rest of the app stays unaware of the dual-backend setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Python AI Service: What It Does
&lt;/h2&gt;

&lt;h3&gt;
  
  
  RAG for Financial Q&amp;amp;A
&lt;/h3&gt;

&lt;p&gt;Users ask questions like &lt;em&gt;"How much did I spend on groceries last month?"&lt;/em&gt; or &lt;em&gt;"What's left in my dining budget?"&lt;/em&gt; The RAG service:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generates an embedding for the user's question&lt;/li&gt;
&lt;li&gt;Searches a vector store for relevant transactions, goals, and spending caps&lt;/li&gt;
&lt;li&gt;Injects that context into the LLM prompt&lt;/li&gt;
&lt;li&gt;Returns an answer grounded in the user's actual data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We store embeddings for transactions, categories, goals, and budgets. Vector search returns the most relevant slices of data, and the model answers from that—no hallucinations about numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch Transaction Classification
&lt;/h3&gt;

&lt;p&gt;When users upload a CSV from their bank, we have dozens or hundreds of uncategorized transactions. The classifier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses the user's existing category hierarchy&lt;/li&gt;
&lt;li&gt;Learns from past classifications (e.g., "Starbucks" → Coffee)&lt;/li&gt;
&lt;li&gt;Returns structured JSON with category and subcategory IDs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We batch transactions to stay within token limits and process them asynchronously for speed. The frontend shows progress and then refreshes the list when done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voice Input
&lt;/h3&gt;

&lt;p&gt;Users can speak a transaction: &lt;em&gt;"Fifty dollars at the gas station for fuel."&lt;/em&gt; The voice parser turns that into structured fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amount: 50&lt;/li&gt;
&lt;li&gt;Description: Gas station&lt;/li&gt;
&lt;li&gt;Category: Transportation&lt;/li&gt;
&lt;li&gt;Subcategory: Fuel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The transcript is sent to the Python service, which returns a transaction object ready for the user to confirm or edit before saving.&lt;/p&gt;




&lt;h2&gt;
  
  
  Patterns That Worked
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Context-Aware AI
&lt;/h3&gt;

&lt;p&gt;The RAG service receives &lt;code&gt;user_id&lt;/code&gt; and &lt;code&gt;household_id&lt;/code&gt; from the auth token. Every query is scoped to that user's data. There's no risk of leaking one household's finances into another's answers.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Rate Limiting and Usage Tiers
&lt;/h3&gt;

&lt;p&gt;AI calls are expensive. We enforce per-user limits: X chat queries, Y voice sessions, Z classifications per month. Free users get a taste; paid users get more. Limits are checked in middleware before any AI logic runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Caching Where It Makes Sense
&lt;/h3&gt;

&lt;p&gt;Stateless questions like &lt;em&gt;"What's my total income this year?"&lt;/em&gt; can be cached. We cache by query + user_id with a short TTL. Conversational threads aren't cached—they're too dynamic.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Tool Calling for Actions
&lt;/h3&gt;

&lt;p&gt;The chat isn't just Q&amp;amp;A. Users can say &lt;em&gt;"Add twenty dollars for lunch"&lt;/em&gt; and the AI triggers a tool that creates a transaction. We define tool schemas (add_transaction, get_balance, etc.) and the LLM decides when to call them. The Python service executes the call and returns the result for the model to summarize.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start with the dual-backend split from day one.&lt;/strong&gt; I flirted with a monolith and then split. Migrating mid-build was painful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardize error handling early.&lt;/strong&gt; &lt;a href="https://expresso-ts.com" rel="noopener noreferrer"&gt;ExpressoTS&lt;/a&gt; and Python return errors in different shapes. I added a shared error format layer later—would've saved time to do it upfront.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invest in embedding pipelines sooner.&lt;/strong&gt; RAG quality depends on good embeddings. We iterated on what to embed (full transaction text vs. summaries) and when to re-index. Doing that earlier would have improved the chat experience faster. There's more to it, obviously can't reveal all strategies used, but this is a good start. :)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;Building an AI-powered app doesn't mean throwing everything into one stack, specially if you're vibe coding (be cautious). Splitting the backend—ExpressoTS for CRUD, Python for AI—gave me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear ownership of API keys and AI logic&lt;/li&gt;
&lt;li&gt;The right tool for each job&lt;/li&gt;
&lt;li&gt;Independent scaling, concurrency, and deployment&lt;/li&gt;
&lt;li&gt;A maintainable codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're considering adding AI to an existing app, or starting fresh with AI in mind, a dedicated Python, rust or c++ service for all AI workloads is a pattern that scales well.&lt;/p&gt;




&lt;h2&gt;
  
  
  Performance and Cost: Why This Matters When You're Starting Out
&lt;/h2&gt;

&lt;p&gt;When you're building your first product or bootstrapping a side project, every dollar counts. Hosting an app and running AI can get expensive fast. This architecture helps on both fronts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concurrency without over-provisioning.&lt;/strong&gt; The dual-backend split means CRUD and AI run on different processes. The ExpressoTS API can handle thousands of lightweight requests (transactions, account fetches, auth checks) on a modest instance, while the Python service runs AI jobs asynchronously. We're not paying for one beefy server that sits idle waiting for AI calls—we right-size each service. A small Node instance for the API and a small Python instance for AI often cost less than a single large monolith trying to do both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lower infrastructure cost.&lt;/strong&gt; By isolating AI workloads, we avoid scaling the entire app when chat usage spikes. A free-tier or low-cost Python host can handle the AI service early on. As usage grows, we scale only that service. The CRUD API stays stable and cheap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost-effective from day one.&lt;/strong&gt; I built this understanding that building and hosting has to be cost-effective, especially for developers starting their own business. You don't need Kubernetes or a fleet of containers to launch. Two small services, clear boundaries, and the ability to scale each independently—that's a path that keeps bills low while you validate your product.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm the developer behind &lt;a href="https://www.fintrackai.app" rel="noopener noreferrer"&gt;FinTrack&lt;/a&gt;, a personal finance app with an AI called Finny as your best advisor. If you're building something similar, I'd love to hear how you approached it—drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>startup</category>
    </item>
    <item>
      <title>NPM Shield</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Mon, 17 Mar 2025 21:23:50 +0000</pubDate>
      <link>https://dev.to/expressots/npm-shield-31ep</link>
      <guid>https://dev.to/expressots/npm-shield-31ep</guid>
      <description>&lt;p&gt;🚀 Introducing NPM Shield – Secure Dependencies 🛡️&lt;/p&gt;

&lt;p&gt;Two months ago, we launched Better NPM. Since then, we've received numerous feature requests, UI improvement suggestions, and valuable feedback—including constructive criticism. We listened carefully, tested the waters, and understood developers' needs regarding dependency management, security, detailed package insights, and robust analytics.&lt;/p&gt;

&lt;p&gt;Today, we're excited to announce the next evolution—now rebranded as NPM Shield!&lt;/p&gt;

&lt;p&gt;Why NPM Shield? Because it reflects our commitment to protecting your projects through transparency, robust analytics, and comprehensive security.&lt;/p&gt;

&lt;p&gt;Here's what's new and improved: &lt;/p&gt;

&lt;p&gt;✅ Advanced Security Scans – Instantly identify vulnerabilities and risks across your entire dependency tree (CVE and CVSS).&lt;br&gt;
✅ Detailed Package Insights – Gain deeper visibility into maintenance, adoption, and community health of your dependencies.&lt;br&gt;
✅ Dependency Tree Graphs – Visualize your project's dependencies clearly and intuitively.&lt;br&gt;
✅ Risk Mitigation Tools – Proactively address and fix dependency risks before they affect your project.&lt;/p&gt;

&lt;p&gt;🔗 Check it out here: &lt;a href="//store.expresso-ts.com"&gt;NPM Shield&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A huge thank you to the community for your invaluable feedback. Your insights have shaped NPM Shield, helping us build a smarter, safer, and more transparent package ecosystem.&lt;/p&gt;

&lt;p&gt;💬 We're eager to hear your thoughts on NPM Shield—your feedback drives continuous improvement!&lt;/p&gt;

&lt;p&gt;Let's build secure, reliable software together. 💪&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7307508616893276161" rel="noopener noreferrer"&gt;Our LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>expressots</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
    <item>
      <title>Better NPM</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Wed, 19 Feb 2025 08:27:14 +0000</pubDate>
      <link>https://dev.to/expressots/better-npm-4ld6</link>
      <guid>https://dev.to/expressots/better-npm-4ld6</guid>
      <description>&lt;p&gt;🚀 Reimagining NPM: A Smarter, More Secure Package Ecosystem&lt;/p&gt;

&lt;p&gt;🌐  &lt;a href="https://store.expresso-ts.com/" rel="noopener noreferrer"&gt;Better NPM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Package managers—from npm to vcpkg, Conan, Cargo, nuget-dotnet, pip, Maven, and beyond—often fail to give you a complete view of a package before you add it to your project. In today’s rapidly expanding (and often insecure) internet, developers need better tools and insights to ensure that each dependency they bring in is secure, well-maintained, and widely adopted.&lt;/p&gt;

&lt;p&gt;Many organizations take security seriously, yet still rely on patchwork solutions that small companies often can’t afford. That’s why we built a lightweight layer on top of NPM—we’re calling it Better NPM – ExpressoTS Store—to deliver a comprehensive view of every package you consider. This includes data on security breaches, maintenance status, and adoption rates. We’re also focusing on providing ecosystem-wide details that help you scan your project, spot potential vulnerabilities, and make truly informed decisions when selecting dependencies. (SCAN in development)&lt;/p&gt;

&lt;p&gt;Why Better NPM – ExpressoTS Store?&lt;/p&gt;

&lt;p&gt;✅ Transparency: Gain rich insights into package security, maintenance activity, and adoption statistics.&lt;br&gt;
✅ ExpressoTS Plugin Hub: Discover all plugins built for the ExpressoTS Framework in one place.&lt;br&gt;
✅ Better Analytics for Maintainers: Understand how packages are used and receive feedback on how to improve them (feature in development).&lt;br&gt;
✅ A Unified Marketplace: A central hub for vetted plugins and extensions, ensuring consistency and quality.&lt;/p&gt;

&lt;p&gt;🔐 Security at the Core: Stop scavenging GitHub issues and third-party tools. Our goal is to arm you with detailed security info up front, so you can focus on building rather than endlessly verifying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to know more?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;📩 Reach out our Tech Evangelist: &lt;a href="https://www.linkedin.com/in/umataldetatiana/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/umataldetatiana/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🚀 Check out our very beta store: &lt;a href="https://lnkd.in/gGKMHzN6" rel="noopener noreferrer"&gt;https://lnkd.in/gGKMHzN6&lt;/a&gt;&lt;br&gt;
Let’s build a better, smarter package ecosystem together! 💡&lt;/p&gt;

</description>
      <category>npm</category>
      <category>javascript</category>
      <category>node</category>
      <category>expressots</category>
    </item>
    <item>
      <title>3.0 is Here!</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Thu, 05 Dec 2024 18:21:47 +0000</pubDate>
      <link>https://dev.to/expressots/30-is-here-3m7l</link>
      <guid>https://dev.to/expressots/30-is-here-3m7l</guid>
      <description>&lt;h2&gt;
  
  
  ExpressoTS v3.0 is Here! 🎉
&lt;/h2&gt;

&lt;p&gt;This major update brings significant enhancements to ExpressoTS Framework.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduced Dependencies: Streamlined for lighter and faster applications.&lt;/li&gt;
&lt;li&gt;Custom IoC Container&lt;/li&gt;
&lt;li&gt;Embedded Environment Management: Now built into the framework for simplicity.&lt;/li&gt;
&lt;li&gt;New @expressots/shared Package: Consolidates utilities for modular development.&lt;/li&gt;
&lt;li&gt;Micro API Template: Quickly prototype microservices for enhanced scalability.&lt;/li&gt;
&lt;li&gt;Streamlined Application Structure: Centralized configuration in app.ts for easier maintenance.&lt;/li&gt;
&lt;li&gt;Rendering Engine Support: Use EJS, Handlebars, Pug, and more via plugins.&lt;/li&gt;
&lt;li&gt;Plugin System: Extend functionality effortlessly with custom plugins.&lt;/li&gt;
&lt;li&gt;CLI Improvements: Enhanced commands, performance boosts, supporting npm, yarn, and pnpm.&lt;/li&gt;
&lt;li&gt;Improved Testing: Migrated to Jest with extensive unit tests and high coverage. Thanks to &lt;a href="https://www.startearly.ai/" rel="noopener noreferrer"&gt;Early AI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Improved security score, thanks to &lt;a href="https://snyk.io/advisor/npm-package/@expressots/core" rel="noopener noreferrer"&gt;Snyk Health Package Extension&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more information checkout the full article &lt;a href="https://lnkd.in/gEhPgUau" rel="noopener noreferrer"&gt;here&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>expressots</category>
      <category>api</category>
    </item>
    <item>
      <title>"How the Open Source Project Uses EarlyAI to Enhance Framework Code Quality"!</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Mon, 04 Nov 2024 16:52:12 +0000</pubDate>
      <link>https://dev.to/expressots/how-the-open-source-project-uses-earlyai-to-enhance-framework-code-quality-2cei</link>
      <guid>https://dev.to/expressots/how-the-open-source-project-uses-earlyai-to-enhance-framework-code-quality-2cei</guid>
      <description>&lt;h2&gt;
  
  
  Join us on November 12 for an exclusive webinar:
&lt;/h2&gt;

&lt;p&gt;In this webinar, Richard Zampieri ( &lt;a class="mentioned-user" href="https://dev.to/rsaz"&gt;@rsaz&lt;/a&gt; ) and Sharon Barr will share how EarlyAI is used by @ExpressoTS to generate high coverage, quality unit tests in a click.&lt;/p&gt;

&lt;p&gt;ExpressoTS’s approach focuses on more than just code coverage; it’s about gaining rapid insights to improve code quality directly through unit tests generated by EarlyAI. This tool acts as both a time-saver and a proactive bug detector, helping developers quickly identify areas for enhancement.&lt;/p&gt;

&lt;p&gt;Don’t miss out on this chance to see how EarlyAI can transform the future of software development!&lt;/p&gt;

&lt;p&gt;📅 Date: Tuesday, November 12&lt;br&gt;
⏰ Time: 11am PST | 2pm EST | 9pm IL&lt;br&gt;
🔗 Register: &lt;a href="https://lnkd.in/dTsnNrBu" rel="noopener noreferrer"&gt;https://lnkd.in/dTsnNrBu&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>Unit Test Generation with Early AI</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Sun, 20 Oct 2024 08:47:41 +0000</pubDate>
      <link>https://dev.to/rsaz/unit-test-generation-with-early-ai-31co</link>
      <guid>https://dev.to/rsaz/unit-test-generation-with-early-ai-31co</guid>
      <description>&lt;h2&gt;
  
  
  Accelerating Unit Test Generation and Improving Code Quality
&lt;/h2&gt;

&lt;p&gt;Recently, I had the opportunity to deep-dive into &lt;a href="https://www.startearly.ai/" rel="noopener noreferrer"&gt;Early&lt;/a&gt;, an AI agent designed for automatic unit test generation. As someone who regularly works with TypeScript and ExpressoTS Framework, I was keen to see how Early could streamline my workflow. I decided to test the &lt;a href="https://marketplace.visualstudio.com/items?itemName=Early-AI.EarlyAI" rel="noopener noreferrer"&gt;vscode extension&lt;/a&gt; they built on my new NPM library I was developing called &lt;a href="https://github.com/expressots/shared" rel="noopener noreferrer"&gt;@expressots/shared&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial Impressions
&lt;/h3&gt;

&lt;p&gt;The first thing that struck me about Early was its ability to automatically generate unit tests for my existing codebase. Instead of crafting tests from scratch, I could focus on refining the generated tests and improving my code's robustness and testability. This shift significantly accelerated my development process. The other interesting aspect I noticed is that 83% of the code generated I didn't do any adjustment, it worked out of the box and increased my code coverage. Save me a huge time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time Savings and Increased Coverage
&lt;/h3&gt;

&lt;p&gt;In just 8.5 hours, I managed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate unit tests for approximately 3,000 lines of code.&lt;/li&gt;
&lt;li&gt;Fix issues and enhance code testability.&lt;/li&gt;
&lt;li&gt;Achieve a total code coverage of 88% with 96 tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fact that I could accomplish all this in a single day was remarkable. The ideal scenario in unit test is do it while you're actually developing your functions. I did after the fact that I had already a library in place, so some adjustments were necessary to make the code testable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Positive Outcomes
&lt;/h3&gt;

&lt;p&gt;Automatic Generation of Edge Case Tests. For instance, it generated unit tests for scenarios involving empty strings, even when parameters were required:&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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;printSuccess&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;component&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;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;green&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;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="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;white&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;component&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] ✔️\n`&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;Initially, I wouldn't have created tests for empty strings in such a straightforward function. However, Early's approach promoted defensive programming practices, pushing me to handle edge cases I might have overlooked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detection of Potential Issues
&lt;/h3&gt;

&lt;p&gt;While refining the generated tests, I encountered a type mismatch issue:&lt;/p&gt;

&lt;p&gt;Problem: jest.fn() returns any, but process.exit returns never, leading to a type mismatch in TypeScript.&lt;br&gt;
Solution: Modify the mock to match the process.exit signature, ensuring type correctness.&lt;br&gt;
This discovery prompted me to adjust my code for better type safety, highlighting how Early can help identify subtle issues that might otherwise go unnoticed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Areas for Improvement
&lt;/h3&gt;

&lt;p&gt;Despite the overall positive experience, I encountered a few challenges that, if addressed, could enhance Early's usability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Library Version Compatibility. Early generated tests using deprecated Jest methods in some cases, for example:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Jest 29.7&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Compiler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;rejects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toThrowError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;process.exit() was called with code 1&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;// Corrected version&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Compiler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;rejects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;process.exit() was called with code 1&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;ul&gt;
&lt;li&gt;Customization Options for Test Generation
While generating tests for edge cases was beneficial, in some scenarios, it might not be necessary:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Observation: Generating tests for every possible input, including empty strings, can sometimes be overkill.&lt;/p&gt;

&lt;p&gt;Suggestion: Introduce options to customize the level of test generation, allowing developers to opt-in for defensive programming tests as needed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User Interface Enhancements in the VSCODE Extension
Navigating between Early and other tools highlighted some UI limitations:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Test Results Visibility: I had to switch between Early and Jest to see which tests passed or failed.&lt;/p&gt;

&lt;p&gt;File Tree State: The project hierarchy in Early collapses when switching back from other applications, requiring me to reopen folders repeatedly.&lt;br&gt;
Suggestion: Improve the UI to display test results within Early, mirroring Jest's structure. Maintaining the state of the file tree would also enhance user experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezd2k8xyipbff04wv44z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezd2k8xyipbff04wv44z.jpg" alt="Early+Jest View" width="489" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mocking and Type Safety
The issue with jest.fn() returning any suggests a need for more precise mocking:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Observation: Using any types in mocks can lead to type mismatches and potentially mask bugs.&lt;br&gt;
Suggestion: Refine mock generation to use accurate signatures, promoting better type safety and reducing the need for manual corrections.&lt;/p&gt;

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

&lt;p&gt;Overall, my experience with Early was highly positive. The tool significantly accelerated my unit testing process, allowing me to focus on refining tests rather than writing them from scratch. It also encouraged me to consider edge cases and improve my code's robustness.&lt;/p&gt;

&lt;p&gt;The areas for improvement are relatively minor and revolve around enhancing usability and customization. Addressing these would make the tool even more powerful ally in software development.&lt;/p&gt;

&lt;p&gt;Kudos to the Early team for their excellent work! I'm excited to see how the tool evolves and would be happy to continue providing feedback to help refine it further.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extras (CodeCov + Early)
&lt;/h3&gt;

&lt;p&gt;A great way to enhance your code quality and coverage measurement is by integrating &lt;a href="https://about.codecov.io/" rel="noopener noreferrer"&gt;Codecov&lt;/a&gt;. Combining Early AI with Codecov creates a powerful first line of defense for ensuring high-quality code from the start.&lt;/p&gt;

&lt;p&gt;Here is the repo in case someone want's to check it out: &lt;a href="https://github.com/expressots/shared" rel="noopener noreferrer"&gt;@expressots/shared&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Badges:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fam9d7uo260opcsayr15o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fam9d7uo260opcsayr15o.png" alt="ExpressoTS Repo Shared Badges" width="764" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CodeCov:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumi8f7shk5rh57czssub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumi8f7shk5rh57czssub.png" alt="CodeCov" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Drilling more on CodeCov:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpy2qau3ppc3moyild6i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvpy2qau3ppc3moyild6i.png" alt="CodeCov" width="800" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll have clear insights into which parts of your code were covered and which weren't, making it easier to identify areas for improvement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkjnvqxifljgyds11m2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkjnvqxifljgyds11m2o.png" alt="CodeCov" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>ExpressoTS surpassed AdonisJs</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Mon, 09 Sep 2024 20:04:13 +0000</pubDate>
      <link>https://dev.to/expressots/expressots-surpassed-adonisjs-3m4j</link>
      <guid>https://dev.to/expressots/expressots-surpassed-adonisjs-3m4j</guid>
      <description>&lt;h2&gt;
  
  
  🚀 Exciting Milestone Alert! 🚀
&lt;/h2&gt;

&lt;p&gt;ExpressoTS has surpassed AdonisJS in weekly downloads after just 1.5 years! 🎉 We're quickly becoming the go-to framework for #NodeJS &amp;amp; #TypeScript devs. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7238994156365225985" rel="noopener noreferrer"&gt;Full details here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>expressots</category>
      <category>typescript</category>
      <category>news</category>
      <category>node</category>
    </item>
    <item>
      <title>Exploring Rust in a Professional Setting: A C++ Engineer’s Perspective</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Wed, 07 Aug 2024 19:17:50 +0000</pubDate>
      <link>https://dev.to/rsaz/exploring-rust-in-a-professional-setting-a-c-engineers-perspective-4bml</link>
      <guid>https://dev.to/rsaz/exploring-rust-in-a-professional-setting-a-c-engineers-perspective-4bml</guid>
      <description>&lt;p&gt;With over 23 years of experience as a C++ engineer, I’ve seen a lot of programming languages and technologies evolve. I’ve always been eager to explore new tools, and recently, I decided to dive into Rust. My current role as a Principal Engineer at a tech company gave me the perfect opportunity to try Rust in a real-world, professional setting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project: System B Communication Layer
&lt;/h2&gt;

&lt;p&gt;We recently started developing a robotics system, and I was tasked with building the architecture for communication between the system A and the system B. This involved creating a layer that interfaces with the System B using ROS2 and delivers messages to a desktop application.&lt;/p&gt;

&lt;p&gt;For this layer’s API, I decided to give Rust a try. I bought a book, went through the entire tutorial, and got up to speed fairly quickly. For the UI, I chose Tauri as the framework for the desktop application, using Vue for the front-end.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Impressions: A New Development Pattern
&lt;/h2&gt;

&lt;p&gt;Rust’s programming paradigm is quite different from what I was used to with C++. If you come into Rust with an OOP mindset, you’re likely to struggle at first. Rust encourages a different way of thinking about memory management, ownership, and concurrency.&lt;/p&gt;

&lt;p&gt;One of the biggest challenges I faced was dealing with the compiler. Rust’s compiler is notoriously strict, and you’ll spend a lot of time wrestling with it until you understand how it works. However, this is also one of Rust’s strengths. The compiler forces you to write safe, reliable code, which leads to fewer runtime errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Crate Ecosystem: A Mixed Bag
&lt;/h2&gt;

&lt;p&gt;Rust has a vast ecosystem of crates (libraries), which can be both a blessing and a curse. On one hand, there are millions of crates available for almost anything you can think of. On the other hand, many of these crates are low quality, and it can be challenging to find the ones that are truly useful.&lt;/p&gt;

&lt;p&gt;If you’re serious about using Rust in a professional setting, you’ll need to be selective about the crates you rely on. The good news is that once you find the right tools, Rust’s ecosystem can be incredibly powerful.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Turning Point: Embracing Rust’s Philosophy
&lt;/h2&gt;

&lt;p&gt;After a while, I started to get the hang of Rust’s philosophy. I stopped fighting with the compiler and began to enjoy the coding process. One thing that really stood out to me was how reliable my code became. In C++, I’m used to dealing with warnings and errors during compilation, but with Rust, my code compiled cleanly and just worked.&lt;/p&gt;

&lt;p&gt;The sense of security that comes from knowing your code is stable and reliable is one of Rust’s biggest advantages. It’s not something you often experience with C++.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust in Production: A Balanced View
&lt;/h2&gt;

&lt;p&gt;In my experience, Rust is absolutely production-ready. It’s a joy to work with, and the language’s emphasis on safety and reliability is a huge plus. However, the ecosystem still has some catching up to do. I found myself building a lot of tooling and writing my own libraries to fill in the gaps for my specific project.&lt;/p&gt;

&lt;p&gt;If you’re considering Rust for a professional project, be prepared to invest some time in building out your own tools and libraries. The language itself is fantastic, but you may need to do some extra work to get everything you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts: A Positive Outlook
&lt;/h2&gt;

&lt;p&gt;Rust has a lot to offer, especially for developers who value safety, performance, and reliability. While the ecosystem is still maturing, the language itself is rock solid and ready for prime time. If you’re up for the challenge, Rust can be a rewarding addition to your toolkit.&lt;/p&gt;

&lt;p&gt;In conclusion, Rust is a joy to program in, even if it requires some adjustment and a bit of extra effort. As the ecosystem continues to grow, I’m confident that Rust will become an increasingly popular choice for professional development. It’s already proven itself in my experience, and I’m excited to see where it goes from here.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>ExpressoTS on The Rise???</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Sun, 28 Jul 2024 03:22:23 +0000</pubDate>
      <link>https://dev.to/expressots/expressots-on-the-rise-1d5e</link>
      <guid>https://dev.to/expressots/expressots-on-the-rise-1d5e</guid>
      <description>&lt;p&gt;Hi Dev Community,&lt;/p&gt;

&lt;p&gt;Over the past 3 to 4 weeks, we've observed a noticeable increase in downloads of the ExpressoTS framework. Let’s hope this upward trend continues! 🥂&lt;/p&gt;

&lt;p&gt;Thank you for your contributions, engagement, and feedback. Your efforts have been instrumental in enhancing the platform and creating a better developer experience.&lt;/p&gt;

&lt;p&gt;Best,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7qn2ha07e5q0bgnin4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7qn2ha07e5q0bgnin4z.png" alt="ExpressoTS NPM Stats" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>expressots</category>
      <category>framework</category>
      <category>typescript</category>
      <category>node</category>
    </item>
    <item>
      <title>ExpressoTS Render Engine</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Tue, 23 Jul 2024 08:19:46 +0000</pubDate>
      <link>https://dev.to/expressots/expressots-render-engine-2lpi</link>
      <guid>https://dev.to/expressots/expressots-render-engine-2lpi</guid>
      <description>&lt;h2&gt;
  
  
  Render Engine
&lt;/h2&gt;




&lt;p&gt;&lt;strong&gt;&lt;a href="https://expresso-ts.com/" rel="noopener noreferrer"&gt;ExpressoTS&lt;/a&gt;&lt;/strong&gt; enhances the web server capabilities of Express.js by providing a streamlined experience for rendering views. ExpressoTS supports various render engines out-of-the-box, including EJS, PUG, and Handlebars (HBS). This makes it easy for developers to start rendering views without needing additional configuration, as default settings are provided for each supported engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported Render Engines
&lt;/h2&gt;

&lt;p&gt;ExpressoTS supports the following render engines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  EJS&lt;/li&gt;
&lt;li&gt;  PUG&lt;/li&gt;
&lt;li&gt;  HBS (Handlebars)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Handlebars Configuration Options
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;HandlebarsOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;viewEngine&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="c1"&gt;// The view engine to be used&lt;/span&gt;
    &lt;span class="nl"&gt;viewsDir&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="c1"&gt;// The path to the views folder&lt;/span&gt;
    &lt;span class="nl"&gt;partialsDir&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="c1"&gt;// The path to the partials folder&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Default Handlebars configuration options
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;viewEngine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hbs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;viewsDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;/views&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;    &lt;span class="nx"&gt;partialsDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;/views/&lt;/span&gt;&lt;span class="nx"&gt;partials&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;
  
  
  Default Folder structure
&lt;/h3&gt;

&lt;p&gt;Default folder structure for Handlebars:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src
views
|--partials
|   |--partial.hbs
|--index.hbs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All other engines follow the same structure, with the exception of the &lt;code&gt;partials&lt;/code&gt; folder, which is specific to Handlebars.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handlebars File Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;HBS Example&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello from HBS&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Render partial: {{&amp;gt; partial}}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Other Engine Configuration Options
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pug Configuration Options
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PugOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;viewEngine&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="nl"&gt;viewsDir&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Default Pug configuration options
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;viewEngine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pug&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;viewsDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;/views&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  EJS Configuration Options
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;EjsOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;viewsDir&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="nl"&gt;viewEngine&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="nl"&gt;serverOptions&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;EjsOptionsServer&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;h4&gt;
  
  
  Default EJS configuration options
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;viewEngine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ejs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;viewsDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;/views&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;    &lt;span class="nx"&gt;serverOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;cache&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;compileDebug&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="nx"&gt;debug&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="nx"&gt;delimiter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;strict&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;
  
  
  How to use
&lt;/h2&gt;

&lt;p&gt;Here's how you can set up ExpressoTS to use a render engine like HBS (handlebars) in your application:&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;app.provider&lt;/code&gt; configuration provider, you can set the render engine:&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;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AppExpress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IMiddleware&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProviderManager&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;container&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;IMiddleware&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;Middleware&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;container&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="nx"&gt;ProviderManager&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;configureServices&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Set the render engine to HBS&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEngine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HBS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setErrorHandler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;postServerInitialization&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&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="nx"&gt;Env&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;checkAll&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;protected&lt;/span&gt; &lt;span class="nf"&gt;serverShutdown&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&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;If you want to pass custom options to the render engine, you can do so by passing an object with the desired options to the &lt;code&gt;setEngine&lt;/code&gt; method. For example, to set the views directory to a custom path, you can do the following:&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setEngine&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HBS&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;Engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HBS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;viewsDir&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="nx"&gt;custom&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How To Render Views in ExpressoTS
&lt;/h3&gt;

&lt;p&gt;To render a view in ExpressoTS, you can use the &lt;code&gt;render&lt;/code&gt; method provided by the &lt;code&gt;Response&lt;/code&gt; object. Here's an example of how you can render a view in ExpressoTS:&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;response&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="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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index&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="na"&gt;date&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;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Random information&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, the &lt;code&gt;render&lt;/code&gt; method is called on the &lt;code&gt;Response&lt;/code&gt; object, passing the name of the view to be rendered and an object with data to be passed to the view. The view engine will render the view with the provided data and return the rendered HTML to the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  Render Decorator
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;@Render&lt;/code&gt; decorator can be used on controller methods to render views using the specified view engine. Here's an example of how you can use the &lt;code&gt;@Render&lt;/code&gt; decorator to render a view in ExpressoTS:&lt;/p&gt;

&lt;h4&gt;
  
  
  Rendering passing the view and default data in the decorator
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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="nd"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index&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="na"&gt;date&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;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Random information&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;root&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;h4&gt;
  
  
  Rendering passing only the view in the decorator
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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="nd"&gt;Render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;root&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;date&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;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Random information&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Happy Coding! 🐎&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>expressots</category>
      <category>typescript</category>
    </item>
    <item>
      <title>ExpressoTS - DB in Memory</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Sat, 06 Jul 2024 05:16:36 +0000</pubDate>
      <link>https://dev.to/expressots/expressots-db-in-memory-259n</link>
      <guid>https://dev.to/expressots/expressots-db-in-memory-259n</guid>
      <description>&lt;p&gt;Explore our In-Memory DB in action! 🐎&lt;/p&gt;

&lt;p&gt;This straightforward class enables developers to prototype APIs effortlessly, eliminating the need to connect to or set up database. Perfect for rapid development and testing! &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gT4-QZCh1eU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>node</category>
      <category>api</category>
      <category>learning</category>
    </item>
    <item>
      <title>Enhancing Rust Development: Introducing cargo-run for Script Management</title>
      <dc:creator>Richard Zampieri</dc:creator>
      <pubDate>Thu, 27 Jun 2024 21:18:01 +0000</pubDate>
      <link>https://dev.to/rsaz/enhancing-rust-development-introducing-cargo-run-for-script-management-kfb</link>
      <guid>https://dev.to/rsaz/enhancing-rust-development-introducing-cargo-run-for-script-management-kfb</guid>
      <description>&lt;p&gt;In the world of modern software development, package managers have become indispensable tools for developers. Languages like JavaScript/TypeScript (with npm/yarn), C++ (with CMake), and Java (with Maven/Gradle) all have sophisticated package managers that include powerful scripting capabilities. These script sections allow users to define custom build, prebuild, and test scripts, enhancing their development workflow.&lt;/p&gt;

&lt;p&gt;However, when it comes to Rust, the Cargo package manager doesn't offer a built-in scripting feature in the Cargo.toml file. This often leads developers to rely on lengthy and complex command lines for various tasks. Recognizing this gap, I created a new crate called &lt;a href="https://crates.io/crates/cargo-run" rel="noopener noreferrer"&gt;cargo-run&lt;/a&gt; that brings flexible, powerful scripting capabilities to the Rust ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing cargo-run
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;cargo-run&lt;/code&gt; is a Rust crate designed to run scripts defined in a &lt;code&gt;Scripts.toml&lt;/code&gt; file. It aims to simplify and enhance script management in Rust projects, providing features that rival those found in other language ecosystems. &lt;/p&gt;

&lt;h2&gt;
  
  
  All current features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run scripts defined in Scripts.toml.&lt;/li&gt;
&lt;li&gt;Specify interpreters for scripts (e.g., bash, zsh, PowerShell).&lt;/li&gt;
&lt;li&gt;Initialize a Scripts.toml file with default content.&lt;/li&gt;
&lt;li&gt;Chain multiple scripts together using the include feature.&lt;/li&gt;
&lt;li&gt;Set global environment variables and script-specific environment variables with precedence handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why cargo-run?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;cargo-run&lt;/code&gt; enhances the user script management and build process in ways that the standard build.rs file cannot. While build.rs is great for build-specific tasks, cargo-run allows you to define a wide range of scripts, from build and prebuild to testing, deployment, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  User-Friendly and Clean UI
&lt;/h2&gt;

&lt;p&gt;One of the standout features of cargo-run is its readable and clean UI. When running scripts, cargo-run provides clear output, showing which script is currently running and the status of each script. This makes it easy for users to follow along with the script execution process and identify any issues quickly.&lt;/p&gt;

&lt;p&gt;Here are a few scenarios where cargo-run shines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex Build Pipelines: Define complex build pipelines that involve multiple steps and tools, all orchestrated through cargo-run scripts.&lt;/li&gt;
&lt;li&gt;Cross-Platform Development: Use different interpreters to ensure your scripts run smoothly on different operating systems.&lt;/li&gt;
&lt;li&gt;Environment Management: Manage environment variables effortlessly, ensuring your scripts have the right configuration for different environments (e.g., development, testing, production).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example: Getting Started with cargo-run
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Initialize Scripts.toml
&lt;/h3&gt;

&lt;p&gt;First, initialize your Scripts.toml file with default content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cgs run init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Define a Script
&lt;/h3&gt;

&lt;p&gt;Next, define a simple build script in Scripts.toml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[scripts]&lt;/span&gt;
&lt;span class="py"&gt;build&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"echo 'build'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Run the Script
&lt;/h3&gt;

&lt;p&gt;Run the script using cargo-run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cgs run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Chain Scripts Together
&lt;/h3&gt;

&lt;p&gt;You can chain multiple scripts together using the include feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[scripts]&lt;/span&gt;
&lt;span class="py"&gt;release&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"i_am_shell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"build"&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;For more examples read the &lt;a href="https://github.com/rsaz/cargo-script" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;cargo-run&lt;/code&gt; crate offers a powerful, flexible way to manage scripts in Rust projects. By bringing the script management capabilities of other language ecosystems to Rust, cargo-run simplifies complex workflows, enhances cross-platform development, and provides robust environment management.&lt;/p&gt;

&lt;p&gt;Whether you're working on a simple project or a complex application, &lt;code&gt;cargo-run&lt;/code&gt; can help streamline your development process. I encourage you to explore cargo-run and see how it can enhance your Rust development experience.&lt;/p&gt;

&lt;p&gt;To get started, check out the cargo-run crate on &lt;a href="https://crates.io/crates/cargo-run" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; and visit the &lt;a href="https://github.com/rsaz/cargo-script" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; for more details and documentation. Happy scripting!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>development</category>
      <category>utility</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
