<?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: Callgent</title>
    <description>The latest articles on DEV Community by Callgent (@callgent).</description>
    <link>https://dev.to/callgent</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%2F1342125%2F575e831c-fa57-4982-b24d-fd8e5c16b4b0.png</url>
      <title>DEV Community: Callgent</title>
      <link>https://dev.to/callgent</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/callgent"/>
    <language>en</language>
    <item>
      <title>🥙 Callgentive UI - Home-Cooked Software Development</title>
      <dc:creator>Callgent</dc:creator>
      <pubDate>Mon, 17 Jun 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/callgent/callgentive-ui-home-cooked-software-development-2f79</link>
      <guid>https://dev.to/callgent/callgentive-ui-home-cooked-software-development-2f79</guid>
      <description>&lt;p&gt;AI Large Language Models (LLMs) are ushering in a new golden age of &lt;a href="https://maggieappleton.com/home-cooked-software"&gt;Home-Cooked Software&lt;/a&gt;. and callgent is providing the solid infrastructure and solutions to make it happen. Let's take a look at how.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Generative UI?
&lt;/h2&gt;

&lt;p&gt;From now on, forget the traditional software paradigm.&lt;/p&gt;

&lt;p&gt;Imagine if we treated every interaction between a user and an app as a chat, with the only difference being that the content of the chat is not text, but rather a collection of widgets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgr0gfpcl747ah8x4ii4d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgr0gfpcl747ah8x4ii4d.png" alt="textual chat =&amp;gt; widget chat" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Users interact with widgets to send chat requests to AI agents, which then decide how to process the request, encapsulate the result in widgets, and present it to the user in a certain way.&lt;/p&gt;

&lt;p&gt;The underlying layer of the chat is still textual + agents, but the interaction between the user and the app will now take place through a visual widget UI instead of text.&lt;/p&gt;

&lt;p&gt;:::tip&lt;br&gt;
From the end-user's perspective, a Generative App is no different from a traditional app (although a Generative App may appear more personalized).&lt;br&gt;
:::&lt;/p&gt;

&lt;h2&gt;
  
  
  Callgentive UI
&lt;/h2&gt;

&lt;p&gt;How does callgent leverage generative UI, as we name it &lt;code&gt;Callgentive UI&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A picture is worth a thousand words:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnqp9p7wnvea5v44l735.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnqp9p7wnvea5v44l735.png" alt="Callgentive UI" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With predefined business services and standard widgets, the &lt;code&gt;Home-Cooked Software&lt;/code&gt; works as follows,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The landing pages are generative UI of widgets generated from some initializing Agent prompts.&lt;/li&gt;
&lt;li&gt;As user interacts with the widgets, the interactions are transformed into a chat request.&lt;/li&gt;
&lt;li&gt;The backend Callgent maps the chat requests to business service invocations, and gets response data from services.&lt;/li&gt;
&lt;li&gt;The Callgent makes the response data into a set of widgets, and presents it to the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How does it work?
&lt;/h3&gt;

&lt;p&gt;Callgent's core functionality is to do native function-calling to orchestrate business services.&lt;/p&gt;

&lt;p&gt;Callgent has server endpoints and client endpoints to adapt various invocation scenarios.&lt;/p&gt;

&lt;p&gt;Specifically, widget based User Interface, is just one more type of client endpoints, to adapt human interactions.&lt;/p&gt;

</description>
      <category>industrytrends</category>
      <category>architecturepatterns</category>
      <category>productdesign</category>
    </item>
    <item>
      <title>🚀 5 Reasons Why Callgent.com is Revolutionizing Business Operations</title>
      <dc:creator>Callgent</dc:creator>
      <pubDate>Sat, 18 May 2024 09:36:46 +0000</pubDate>
      <link>https://dev.to/callgent/5-reasons-why-callgent-is-revolutionizing-business-operations-opp</link>
      <guid>https://dev.to/callgent/5-reasons-why-callgent-is-revolutionizing-business-operations-opp</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's fast-paced business world, the demand for streamlined operations and seamless integration of disparate systems is more pressing than ever. Callgent emerges as a groundbreaking solution, crafted to address these challenges head-on. This article explores the unique aspects of Callgent that simplify business processes and enhance operational efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Genesis of Callgent.com
&lt;/h2&gt;

&lt;p&gt;Callgent was created with a clear mission: to develop a robust enterprise operation platform capable of effortlessly tracking and processing business tickets from customers or internal systems. we have these initial thoughts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.callgent.com%2Fassets%2Fimages%2Fbest-business-operation-platform-2b7e841320e6bea81c17d4111361fa88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.callgent.com%2Fassets%2Fimages%2Fbest-business-operation-platform-2b7e841320e6bea81c17d4111361fa88.png" title="Best Business Operation Platform" alt="Best Business Operation Platform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a nutshell, we grappled the key issues plaguing businesses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Diverse and Disconnected Systems&lt;/strong&gt;: Businesses often struggle with integrating diverse systems that are not designed to work together.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Varying User Roles and Needs&lt;/strong&gt;: Each user within a business has unique roles and requirements that need tailored solutions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mixture of Data Types&lt;/strong&gt;: Handling both structured and unstructured data effectively is a significant challenge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demand for Automation&lt;/strong&gt;: There is a critical need for automated workflows and processes to improve efficiency and reduce human error.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Core Features of Callgent
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Effortless System Integration
&lt;/h3&gt;

&lt;p&gt;Callgent stands out for its ability to integrate heterogeneous systems without the need for coding. This means that businesses do not have to invest time and resources in learning new APIs. The platform uses AI-powered services to facilitate user and system interactions, making the integration smooth and effortless.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced AI Capabilities
&lt;/h3&gt;

&lt;p&gt;The platform's AI capabilities are particularly noteworthy. Callgent employs semantic data mapping and persistent asynchronous operations, which allow for progressive system and user invocation. These features ensure that the system understands and processes data efficiently, regardless of its format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Natural Language Workflow Automation
&lt;/h3&gt;

&lt;p&gt;Callgent's natural language Standard Operating Procedure (SOP) orchestration allows users to automate complex workflows using simple language commands. This makes it easy for non-technical users to streamline their operations in documentations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Successful Integration Stories
&lt;/h2&gt;

&lt;p&gt;Callgent's effectiveness is proven by its successful integration with various tools and platforms, such as Slack, Zendesk, and Kubernetes (k8s) services. This integration enables users to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invoke related services through APIs with responses via Slack or email.&lt;/li&gt;
&lt;li&gt;Interact with k8s services using natural language commands directly in Slack.&lt;/li&gt;
&lt;li&gt;Ensure that k8s exceptions are integrated into the ticket processing workflow without disrupting the user experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Embracing Open Source and Community
&lt;/h2&gt;

&lt;p&gt;In an exciting development, Callgent is now transitioning to an open-source model. This move will undoubtedly foster a community of developers and users who can contribute to and benefit from the platform. Callgent invites users to try out the platform, share feedback, and even contribute to its development through GitHub.&lt;/p&gt;

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

&lt;p&gt;Callgent signifies a significant leap in business operation platforms, providing a seamless, integrated experience that caters to all systems and users. With its no-code integration, AI-driven capabilities, and user-friendly design, Callgent is poised to revolutionize the enterprise operations landscape. As it enters its open-source phase, the potential for growth and innovation is limitless.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Dive Deeper into Callgent&lt;/strong&gt;: &lt;a href="https://docs.callgent.com/docs/intro" rel="noopener noreferrer"&gt;Get Started with Callgent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Share Your Thoughts&lt;/strong&gt;: &lt;a href="https://callgent.canny.io" rel="noopener noreferrer"&gt;Join the Callgent Community&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be Part of Callgent's Development&lt;/strong&gt;: &lt;a href="https://github.com/Callgent/callgent-api" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>industrytrends</category>
      <category>architecturepatterns</category>
      <category>productdesign</category>
    </item>
    <item>
      <title>Nestjs + Prisma, transaction propagation &amp; test rollback &amp; multi-tenancy</title>
      <dc:creator>Callgent</dc:creator>
      <pubDate>Sat, 16 Mar 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/callgent/nestjs-prisma-transaction-propagation-test-rollback-multi-tenancy-4485</link>
      <guid>https://dev.to/callgent/nestjs-prisma-transaction-propagation-test-rollback-multi-tenancy-4485</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Fti9nyig2nddacp1r0jec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fti9nyig2nddacp1r0jec.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prisma interactive transaction
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Prisma&lt;/code&gt; is great. Yet it's support for &lt;code&gt;interactive transaction&lt;/code&gt; is currently &lt;a href="https://github.com/prisma/prisma/issues/12458" rel="noopener noreferrer"&gt;limited&lt;/a&gt; (Up to v5+),&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// interactive transaction&lt;/span&gt;
&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$transaction&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;array_of_operations&lt;/span&gt;&lt;span class="p"&gt;,]);&lt;/span&gt;

&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// dependent operations&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Container managed transactions
&lt;/h2&gt;

&lt;p&gt;As we integrate Prisma to &lt;code&gt;NestJs&lt;/code&gt;, we want cross &lt;code&gt;Services&lt;/code&gt; transaction propagation, &lt;code&gt;container managed tx&lt;/code&gt; is even better. After some investigation, we come to &lt;a href="https://papooch.github.io/nestjs-cls/plugins/available-plugins/transactional" rel="noopener noreferrer"&gt;@nestjs-cls/transactional&lt;/a&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;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyService&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="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;txHost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TransactionHost&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TransactionalAdapterPrisma&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;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;anotherService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnotherService&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Transactional&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;myMethod&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&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;txHost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// db operations1&lt;/span&gt;
    &lt;span class="k"&gt;await&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;anotherService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;anotherMethod&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// db operations2&lt;/span&gt;
    &lt;span class="c1"&gt;// db operations3&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;Just decorate your &lt;code&gt;Service&lt;/code&gt; method with &lt;code&gt;@Transactional()&lt;/code&gt;, it will automatically propagate the transaction across service calls. Under the hood, it uses &lt;code&gt;cls&lt;/code&gt; (continuation-local storage) to manage the transaction context.&lt;/p&gt;

&lt;p&gt;Rollback is triggered by just throwing an exception.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup the module
&lt;/h3&gt;

&lt;p&gt;&lt;a id="prismaInjectionToken"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;ClsModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&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;ClsPluginTransactional&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;PrismaModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// comment this line, if you have existing PrismaModule&lt;/span&gt;
          &lt;span class="na"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;mount&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="c1"&gt;// mount plugin as nestjs middleware&lt;/span&gt;
          &lt;span class="na"&gt;adapter&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;TransactionalAdapterPrisma&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="c1"&gt;// Prisma adaptor&lt;/span&gt;
            &lt;span class="c1"&gt;// the original PrismaService is wrapped into the adaptor&lt;/span&gt;
            &lt;span class="na"&gt;prismaInjectionToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PrismaService&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="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;More complicated use cases, please read it's &lt;a href="https://papooch.github.io/nestjs-cls/plugins/available-plugins/transactional" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transactions in e2e test cases
&lt;/h2&gt;

&lt;p&gt;After each test case, we need to rollback the transaction, preventing side-effects. Thankfully again, it comes to &lt;a href="https://github.com/chax-at/transactional-prisma-testing#readme" rel="noopener noreferrer"&gt;@chax-at/transactional-prisma-testing&lt;/a&gt;,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// the PrismaService proxy&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;prismaService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This function must be called before every test&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;beforeEachFn&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="nx"&gt;prismaTestingHelper&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;prismaTestingHelper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaTestingHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&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;PrismaService&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;prismaService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prismaTestingHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProxyClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prismaTestingHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startNewTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This function must be called after every test&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;afterEachFn&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;prismaTestingHelper&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;rollbackCurrentTransaction&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;
  
  
  Integrated with @nestjs-cls/transactional
&lt;/h3&gt;

&lt;p&gt;We need this orderly wrapping,&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@nestjs-cls/transactional
  └─@chax-at/transactional-prisma-testing
      └─original-PrismaService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So we override PrismaService with testing proxy in &lt;a id="beforeAllFn"&gt;&lt;code&gt;beforeAllFn&lt;/code&gt;&lt;/a&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/testing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;prismaTestingHelper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prismaServiceForTest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;beforeAllFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moduleFixtureForTest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTestingModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppModule&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="nf"&gt;overrideProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PrismaService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useFactory&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;originalPrisma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PrismaService&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;prismaTestingHelper&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;prismaTestingHelper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaTestingHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalPrisma&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;prismaServiceForTest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prismaTestingHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProxyClient&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="nx"&gt;prismaServiceForTest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;PrismaService&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="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NestFastifyApplication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;moduleFixtureForTest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createNestApplication&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;FastifyAdapter&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;abortOnError&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="na"&gt;bufferLogs&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="c1"&gt;// ... ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Don't forget to call these method around each test,&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;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AppController (e2e)&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;beforeAllFn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;afterAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;afterAllFn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;beforeEachFn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;afterEachFn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api (GET)&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// db operations are rollbacked after each test automatically.&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;🎉 🎉 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Transparent multi-tenancy based on postgreSQL
&lt;/h2&gt;

&lt;p&gt;We have a &lt;a href="https://callgent.io" rel="noopener noreferrer"&gt;multi-tenant application, Botlet.IO&lt;/a&gt;, tenants data are isolated based on the &lt;code&gt;tenant_id&lt;/code&gt; column in db tables.&lt;/p&gt;

&lt;p&gt;By design, we want tenant isolation &lt;strong&gt;transparently&lt;/strong&gt; implemented, so we don't need to add &lt;code&gt;tenant_id&lt;/code&gt; to every query.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// by default, we want the below query to be tenant isolated,&lt;/span&gt;
  &lt;span class="c1"&gt;// only users in context tenant are returned.&lt;/span&gt;
  &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$queryRaw&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM users`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We utilize the postgreSQL row level security(RLS), following &lt;a href="https://github.com/prisma/prisma-client-extensions/tree/main/row-level-security" rel="noopener noreferrer"&gt;this article&lt;/a&gt; to achieve &lt;strong&gt;transparent tenant isolation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;:::note&lt;br&gt;
RLS is only applicable in &lt;code&gt;postgreSQL&lt;/code&gt;&lt;br&gt;
:::&lt;/p&gt;

&lt;h3&gt;
  
  
  How to implement
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;in &lt;code&gt;schema.prisma&lt;/code&gt; file, set db column &lt;code&gt;tenant_id&lt;/code&gt; default value to context variable &lt;code&gt;tenancy.tenantId&lt;/code&gt;,&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   tenant_id Int  @default(dbgenerated("(current_setting('tenancy.tenantId'))::int"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;enable postgres row level security(RLS), so that we can filter data by &lt;code&gt;tenant_id&lt;/code&gt; automatically:&lt;br&gt;
write SQL in prisma/migrations/01_row_level_security/migration.sql,&lt;br&gt;
please refer this &lt;a href="https://github.com/Callgent/callgent-api/blob/main/prisma/migrations/row_level_security/migration.sql" rel="noopener noreferrer"&gt;real example&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;on each request, preset &lt;code&gt;tenant_id&lt;/code&gt; into &lt;code&gt;cls&lt;/code&gt; context, refer to &lt;a href="https://github.com/Callgent/callgent-api/blob/main/src/users/listeners/auth-logined.listener.ts" rel="noopener noreferrer"&gt;auth-logined.listener.ts&lt;/a&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TENANT_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;curentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;extend &lt;code&gt;PrismaClient&lt;/code&gt; to set &lt;code&gt;tenant_id&lt;/code&gt; before any query, refer to &lt;a href="https://github.com/Callgent/callgent-api/blob/main/src/infra/repo/tenancy/prisma-tenancy.provider.ts" rel="noopener noreferrer"&gt;prisma-tenancy.provider.ts&lt;/a&gt;,&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;   &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;set_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tenancy.tenantId'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'TENANT_ID'&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;ol&gt;
&lt;li&gt;if you want to bypass rls, for example, by admin, or looking up the logon user to determine their tenant ID:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;   &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;POLICY&lt;/span&gt; &lt;span class="n"&gt;bypass_rls_policy&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"User"&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_setting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tenancy.bypass_rls'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'on'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;then when you want to bypass rls, you must set &lt;code&gt;tenancy.bypass_rls&lt;/code&gt; to &lt;code&gt;on&lt;/code&gt; before running the query, refer to &lt;a href="https://github.com/Callgent/callgent-api/blob/main/src/infra/repo/tenancy/prisma-tenancy.service.ts" rel="noopener noreferrer"&gt;prisma-tenancy.service.ts&lt;/a&gt;,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$executeRaw&lt;/span&gt;&lt;span class="s2"&gt;`SELECT set_config('tenancy.bypass_rls', 'on', TRUE)`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  how it works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;tenantId&lt;/code&gt; is set into &lt;code&gt;cls&lt;/code&gt; context on each request from current user.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PrismaClient&lt;/code&gt; is extended on &lt;code&gt;$allOperations&lt;/code&gt; to set &lt;code&gt;tenantId&lt;/code&gt; into db variable &lt;code&gt;tenancy.tenantId&lt;/code&gt; before any query.&lt;/li&gt;
&lt;li&gt;postgreSQL RLS is enabled, so that all queries will be filtered by &lt;code&gt;tenancy.tenantId&lt;/code&gt; automatically.&lt;/li&gt;
&lt;li&gt;on db &lt;code&gt;insert&lt;/code&gt; operation, &lt;code&gt;tenancy.tenantId&lt;/code&gt; is set into &lt;code&gt;tenant_id&lt;/code&gt; column as default value.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Integrate them all
&lt;/h2&gt;

&lt;p&gt;As we extended &lt;code&gt;PrismaClient&lt;/code&gt; to enable transparent multi-tenancy, now the wrapping order is changed to,&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@nestjs-cls/transactional
  └─@chax-at/transactional-prisma-testing
      └─**tenancy-extended-prisma**
        └─original-PrismaService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;extend &lt;code&gt;PrismaClient&lt;/code&gt; as name &lt;code&gt;TENANTED_PRISMA_SERVICE&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Global&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;PrismaModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// original PrismaModule&lt;/span&gt;
  &lt;span class="na"&gt;providers&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="na"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TENANTED_PRISMA_SERVICE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&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;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TENANTED_PRISMA_SERVICE&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// extended PrismaClient&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PrismaTenancyOnPgModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;replace &lt;code&gt;PrismaService&lt;/code&gt; with &lt;code&gt;TENANTED_PRISMA_SERVICE&lt;/code&gt; in &lt;code&gt;prismaInjectionToken&lt;/code&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;replace &lt;code&gt;PrismaService&lt;/code&gt; with &lt;code&gt;TENANTED_PRISMA_SERVICE&lt;/code&gt; in &lt;code&gt;beforeAllFn&lt;/code&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🎉 🎉 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://papooch.github.io/nestjs-cls/plugins/available-plugins/transactional" rel="noopener noreferrer"&gt;@nestjs-cls/transactional&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chax-at/transactional-prisma-testing#readme" rel="noopener noreferrer"&gt;@chax-at/transactional-prisma-testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/prisma/prisma-client-extensions/tree/main/row-level-security" rel="noopener noreferrer"&gt;prisma-client-extensions: RLS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Callgent/callgent-api/blob/main/src/infra/repo/tenancy" rel="noopener noreferrer"&gt;Callgent - multi-tenant application&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>technologystack</category>
      <category>prisma</category>
      <category>nestjs</category>
      <category>tenancy</category>
    </item>
  </channel>
</rss>
