DEV Community

Cover image for SaasRock Update: RowRepository, Blog for Tenants and Prompt Mapping
Alexandro Martinez
Alexandro Martinez

Posted on

SaasRock Update: RowRepository, Blog for Tenants and Prompt Mapping

SaasRock 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.

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" });
Enter fullscreen mode Exit fullscreen mode

Now:

const company = new RowModel(row);
const name = company.getText("name");
const enabled = company.getBoolean("enabled");
Enter fullscreen mode Exit fullscreen mode

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 },
});
Enter fullscreen mode Exit fullscreen mode

Now:

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




⭐ Blog for Tenants

Watch the demo here.

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 and now Blog Posts. But I should've implemented Knowledge Base, Page Blocks, Webhook Events, and 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.

With tools like OpenAI API, I'm trying to leverage some of its power for SaasRock users through the 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 + Supabase (fast!), Fly.io + Fly Postgres (faster!!), and Fly.io + SQLite (fastest!!!).

I stuck with the Fly + Supabase combo 😀.

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
Enter fullscreen mode Exit fullscreen mode




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 to create triggers, and a true workflow, for example: Upon updating a "Contract" entity row -> Run this HTTP request (i.e. DocuSign 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 or Rewardful, 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 and SaasFrontends.

Top comments (0)