ServerCRUD
Services
Effect-TS service implementations for the CRUD engine.
CrudService
Main entry point in services/crud.service.ts.
export class CrudService extends Context.Tag("CrudService") {
static readonly execute = ...
}Interface
interface CrudService {
execute<T>(
model: string,
op: CrudOperation,
params: unknown,
context: CrudContext
): Effect<never, CrudError, T>;
}Responsibilities
- Orchestrates the Operation Pipeline
- Provides high-level API for other features
- Does not perform DB work directly
CrudRepository
Database wrapper in services/crud-repository.service.ts.
// Dynamic delegate selection
const delegate = prisma[model];
return yield* withDbRetry(model, op, Effect.tryPromise({
try: () => delegate[op](params),
catch: (e) => new Error(String(e))
}));Features
- Uses
PrismaTagto access global Prisma client - Dynamic model/delegate selection
- Retry logic via
withDbRetry - Error mapping to
CrudError
CrudHookService
Hook executor in services/crud-hook.service.ts.
Responsibilities
- Resolves hooks from the
crudHooksregistry - Executes
runBeforeHooksto modify params - Executes
runAfterSuccessHooksfor side-effects - Uses shared
hook-executor.tsutility
Hook Context
interface HookContext {
model: string;
op: string;
params: unknown;
result?: unknown;
context: {
org: string;
user: User;
session: Session;
};
}OperationHandlerService
Orchestrates validation, hooks, and repository execution in services/operation-handler.service.ts.
Flow
- Validate input against Zod schema
- Execute before hooks
- Call repository
- Execute after hooks (on success)
- Return result
Dependency Injection
All services are composed in layers.ts:
export const CrudServiceLive = Layer.provide(
CrudService.of({ ... }),
[
CrudRepositoryLive,
CrudHookServiceLive,
MetricsServiceLive,
]
);To use CRUD in an Effect program:
Effect.provide(CrudServiceLive)