SaasRock Update: RowRepository, Blog for Tenants and Prompt Mapping
Tags: blogging, saas, ai, repository
Published: 2023-07-27 05:27:28

---
title: SaasRock Update: RowRepository, Blog for Tenants and Prompt Mapping
published: true
description: Implementing custom code is now easier with RowRepository and RowModel. Tenants can now have their own blog @ /b/:tenant-slug. And Prompt Mapping to create from AI.
tags: blogging,saas,ai,repository
cover_image: https://qwcsbptoezmuwgyijrxp.supabase.co/storage/v1/object/public/novel/1690413906976-YouTube%20Channel%20Art%20(1).png
# Use a ratio of 100:42 for best results.
# published_at: 2023-07-27 04:28 +0000
---

[SaasRock](https://saasrock.com/?ref=dev.to&utm_content=0-9-1-release) 0.9.1 released!

Implementing custom code is now easier with **RowRepository** and **RowModel**. Plus, tenants can now have their own **Blog Posts**. And **Prompt Mapping** to generate content using AI that maps to your entity rows.

**⭐ RowModel and RowRepository**
--------------------------------

[Watch the demo here](https://www.loom.com/share/3b0b74822f164e6284bf38b35bb49ea6?sid=2ba5e8be-cb6c-4cea-af6b-df654a384f17).

SaasRock is heavily leading towards **no code**, so the Entity Builder is becoming one of the most important features. But you can only get to a point with no code. Once you have some basic Entities with Properties and Relationships, you may want to run some custom code, for example, imagine you have a Contract entity, you may want to:

*   Process a Contract entity row upon creation _(onAfterCreate_ **_RowHook_**_)_.
    
*   Override the default Contracts **View Route** _(RowsViewRoute.tsx)_, so it's not just a table with filters and pagination.
    
*   Listen to a **Webhook Event** _(i.e. row.updated)_.
    

And so on.

I know we have the Code Generator to generate all the files regarding your Entity (list, new, overview, edit, DTOs, service to run DB operations...) but sometimes you only want to override a specific route or run something when something happens (RowHook).

I'm not planning to create a full ORM for entity manipulation, but with the newly implemented classes, I hope it's easier.

### **RowModel**

**Server** and **Client** side.

This class encapsulates an entity row _(RowWithDetails)_ so you can get the row property values easier.

In order to use the RowModel abstraction, I load all the entities in an EntitiesSingleton instance at `useAppData()` and `useAdminData()`.

**Before:**

    const name = RowValueHelper.getText({ entity, row, name: "name" });
    const enabled = RowValueHelper.getBoolean({ entity, row, name: "enabled" });

**Now:**

    const company = new RowModel(row);
    const name = company.getText("name");
    const enabled = company.getBoolean("enabled");

### **RowRepository**

**Server**\-side only.

This is an extension for RowModel, with the difference that it can only run in the backend to run async operations, such as `await updateText("property", "value");`

In order to use this class, you must ensure you have called `getAllEntities` or manually load them in the **EntitiesSingleton** instance with `await EntitiesSingleton.load()`.

**Before:**

    await RowValueHelper.update({ entity, row,
      values: [
        { name: "name", textValue: "New name" },
        { name: "enabled", booleanValue: true },
      ],
      session: { tenantId, userId },
    });

**Now:**

    const companyRepository = new RowRepository(item, {
      session: { tenantId, userId },
    });
    await companyRepository.updateText("name", "New name");
    await companyRepository.updateBoolean("enabled", true);

**⭐ Blog for Tenants**
----------------------

[Watch the demo here](https://www.loom.com/share/de15bff448c3460b9585826e46e1df3d?sid=92ae0c02-d558-4db1-a261-b077615de557).

I've had a few requests for this feature. I really should've implemented every admin feature for app users as well. I've done that with a few: [**Email Marketing**](https://saasrock.com/docs/articles/email-marketing) and now [**Blog Posts**](https://saasrock.com/docs/articles/blogging). But I should've implemented [**Knowledge Base**](https://saasrock.com/docs/articles/knowledge-base), [**Page Blocks**](https://saasrock.com/docs/articles/page-blocks), [**Webhook Events**](https://saasrock.com/docs/articles/events-and-webhooks), and [**Onboarding**](https://saasrock.com/docs/articles/onboarding) for app users as well.

Now your app users can create blog posts, and their blog will be at `/b/:tenant-slug` and posts at `/b/:tenant-slug/post-slug`.

But you need to manually enable this at `appConfiguration.db.server.ts` with `tenantBlogs: true` _(I know, it should be a setting at_ `/admin/settings/app-features`_)_.

**⭐ Prompt Mapping**
--------------------

[Watch the demo here](https://www.loom.com/share/3c7a099e48ae45919a2c96f166018d81?sid=07b9c8ff-5d33-47a3-ad21-e65e244a5961).

With tools like [OpenAI API](https://openai.com/blog/openai-api), I'm trying to leverage some of its power for SaasRock users through the [Prompt Flow Builder](https://saasrock.com/docs/articles/prompt-flow-builder). Imagine the Blog Post feature being 100% built on the Entity Builder, this would mean you could create a Prompt Flow to autogenerate blog posts using custom prompts. That's for later. What's implemented right now is basically creating prompt flows to create or update Entity Rows and their properties.

**🔨 Minor Improvements**
-------------------------

I also worked on a few minor bug fixes and improvements:

*   **Bulk Delete:** A new Entity Builder setting.
    
*   **New Property Types**: WYSIWYG (novel with AI) & iframe src.
    

**My Experience with Deployment**
---------------------------------

A few thoughts about the best hosting + database provider for SaasRock apps. This is just my experience, I've deployed to Vercel + Supabase, Vercel + Vercel Postgres, Render + Supabase, Render + Render Postgres, [Fly.io](http://Fly.io) + Supabase (fast!), [Fly.io](http://Fly.io) + Fly Postgres (faster!!), and [Fly.io](http://Fly.io) + SQLite (fastest!!!).

I stuck with the Fly + Supabase combo 😀.

[Fly.io](http://Fly.io) is awesome! My apps run so fast now, highly recommended. This is basically how you deploy in 5 commands:

    fly apps create appname --org orgname
    flyctl secrets set ENV_VAR_1=ABC ... --app appname
    fly deploy --app appname
    fly scale vm shared-cpu-8x --app appname
    fly scale memory 4096 --app appname

**What's Next?**
----------------

First, I'm going to the beach this week. When I come back I'll start working on a **Workflow Engine**. It will start pretty basic, as every other feature does, but my plan is to implement [ReactFlow](https://reactflow.dev/) to create triggers, and a true workflow, for example: Upon updating a "Contract" entity row -> Run this HTTP request (i.e. [DocuSign](https://www.docusign.com/) API to create a signable contract) -> Get the SignUrl field from the HTTP response -> Update the "Contract" row property "signUrl".

Once a minimal setup is ready, I'll start the **Help Desk** feature, and of course, this will validate the **Workflow Engine** _(i.e. send an email when creating an Issue)_.

And don't worry, both **Help Desk** and the **Workflow Engine** will be built for both admin and app users.

The final shiny feature before 1.0 is still Affiliates and Referrals, something like [**Reflio**](https://reflio.com/) or [**Rewardful**](https://www.rewardful.com/), but 100x simpler.

* * *

Thanks a lot to my past and current subscribers. Had this been an open-source project, I may have already abandoned it like with [**NetcoreSaas**](https://netcoresaas.com/) and [**SaasFrontends**](https://saasfrontends.com/).