business-data-access

star 304

Implement or modify ChatbotX business services, repositories, cache invalidation, event emission, and data-access boundaries. Use when app, worker, or integration code needs database-backed reads or mutations without importing db directly.

ChatbotXIO By ChatbotXIO schedule Updated 6/12/2026

name: business-data-access description: >- Implement or modify ChatbotX business services, repositories, cache invalidation, event emission, and data-access boundaries. Use when app, worker, or integration code needs database-backed reads or mutations without importing db directly.

Business Data Access

Use this skill whenever code outside packages/business or packages/database/src/repositories needs database-backed behavior.

Boundary Rule

Do not add direct database imports in:

  • apps/builder
  • apps/worker
  • integrations

These layers call services from @chatbotx.io/business or repositories from @chatbotx.io/database/repositories. Legacy direct db imports are exceptions, not examples to copy.

Allowed direct db usage:

  • packages/business/src/**
  • packages/database/src/repositories/**

Choosing Service vs Repository

Use a business service when the method has business semantics, authorization adjacent constraints, cache invalidation, event emission, composition across tables, or is reused by app and worker code.

Use a repository when the method is a low-level persistence concern such as shard routing, specialized pagination, or reusable raw query mechanics.

Service Pattern

Services live in packages/business/src/<domain>/.

<domain>/
  service.ts
  index.ts

Typical shape:

import { type DatabaseClient, db } from "@chatbotx.io/database/client"
import { BaseService } from "../base.service"

class ExampleService extends BaseService {
  async doThing(props: {
    workspaceId: string
    tx?: DatabaseClient
  }) {
    const { workspaceId, tx = db } = props
    // query/mutate with tx
    await this.invalidateCacheTags([`examples:${workspaceId}`])
  }
}

export const exampleService = new ExampleService()

Also export from:

  • packages/business/src/<domain>/index.ts
  • packages/business/src/index.ts

Transaction Pattern

  • Accept tx?: DatabaseClient in service methods that may compose with other operations.
  • Default to db inside the service: const { tx = db } = props.
  • Pass tx through nested service/repository calls.

Cache and Events

  • Extend BaseService to use invalidateCacheTags().
  • Use withCache from @chatbotx.io/redis only around stable reads with clear keys.
  • Emit domain events from services when mutations affect downstream workflows.
  • Fire-and-forget events should handle .catch(() => {}) if the local pattern does.

Repository Pattern

Repositories live in packages/database/src/repositories/<domain>/.

repositories/<domain>/
  repository.ts
  index.ts

Export new repositories from packages/database/src/repositories/index.ts. Use the drizzle-database skill for schema, relation, and migration work.

App Layer Usage

Builder feature queries/actions should call services:

import { tagService } from "@chatbotx.io/business"

export const listTags = async (params: { workspaceId: string }) => {
  return tagService.list({ workspaceId: params.workspaceId })
}

Workers and integrations follow the same boundary.

Verification

Before finishing:

  • Search changed app/worker/integration files for new direct db imports.
  • Add or update focused service/repository tests when behavior is non-trivial.
  • Run the smallest relevant test/typecheck script from the touched workspace.
Install via CLI
npx skills add https://github.com/ChatbotXIO/ChatbotX --skill business-data-access
Repository Details
star Stars 304
call_split Forks 33
navigation Branch main
article Path SKILL.md
More from Creator