packages/wrap/src/base.service.ts.

WrapService (abstract)

abstract class WrapService {
  protected logger: Logger;
}

Base for any service with no repository attached — orchestration, sync coordination, email, an external-API-calling service, anything that isn’t entity-CRUD-based. Follows the same @Service() + @ValidateDTO() convention as an entity-backed service:

@Service()
class NotificationService extends WrapService {
  @ValidateDTO()
  async send(dto: SendNotificationDTO, c: Context) {
    this.logger.debug("Sending notification", { to: dto.to });
    // ...
  }
}

BaseService<Repo, TCreate?, TUpdate?> (abstract, extends WrapService)

abstract class BaseService<
  Repo extends BaseRepository<any, any, any>,
  TCreate = RepositoryCreate<Repo>,
  TUpdate = RepositoryUpdate<Repo>,
> extends WrapService {
  constructor(protected repository: Repo);
}

Generic CRUD service — everything is derived from the repository type: class FooService extends BaseService<FooRepository> {}. TCreate/TUpdate default to the repository’s own inferred create/update shapes; override either generic to narrow them for the service layer specifically.

Methods

Method Signature Notes
create @ValidateDTO() create(dto: TCreate, c: Context): Promise<RepositoryEntity<Repo>> Validates dto against its DTO schema (found via the paramtype or an instance already matching a registered DTO class) before calling repository.create().
findById findById(id, options?: ServiceFindOptions<Repo>): Promise<RepositoryEntity<Repo> \| null>
findAll findAll(filters?, options?): Promise<RepositoryEntity<Repo>[]>
findPaginated findPaginated(query: PaginationQuery, options?): Promise<PaginatedResponse<RepositoryEntity<Repo>>>
update @ValidateDTO() update(id, dto: TUpdate, c: Context): Promise<RepositoryEntity<Repo>[] \| null> Throws Error("Entity with id ${id} not found") if repository.exists(id) is false — caught by the standard error mapping as a 404 (message contains “not found”).
delete delete(id): Promise<boolean> Same existence check/throw as update.
deleteMultiple deleteMultiple(ids): Promise<{ deletedCount, requestedCount, success }> success is deletedCount === requestedCount.
findBy findBy<K>(field: K, value): Promise<RepositoryEntity<Repo>[]>
findOneBy findOneBy<K>(field: K, value): Promise<RepositoryEntity<Repo> \| null>
findOne findOne(filters?, options?): Promise<RepositoryEntity<Repo> \| null>
count count(filters?): Promise<number>
exists exists(id): Promise<boolean>
findChangedSince findChangedSince(cursor, options?): Promise<SyncPage<RepositoryEntity<Repo>>> Forwards to the repository — see offline sync.
applyBatch applyBatch(changes): Promise<SyncBatchResult> Forwards to the repository.
getStatistics getStatistics(): Promise<EntityStatistics> Forwards to the repository.
interface ServiceFindOptions<Repo> {
  with?: RepositoryWith<Repo>;     // typed populate config, derived from the repository
  includeDeleted?: boolean;
}

Every read method’s options?.with is fully typed against the repository’s registered relations. For a fully-typed populate result beyond what ServiceFindOptions exposes, call the repository directly.

Type helpers (from base.repository.ts, re-exported through the barrel)

type RepositoryEntity<R>  // R's InferEntity<Table>
type RepositoryCreate<R>  // R's TCreate
type RepositoryUpdate<R>  // R's TUpdate
type RepositoryWith<R>    // R's WithConfig<Table>

This site uses Just the Docs, a documentation theme for Jekyll.