152 lines
3.8 KiB
JavaScript
152 lines
3.8 KiB
JavaScript
"use strict";
|
|
/**
|
|
* BaseService - Abstract Service with Common CRUD Operations
|
|
*
|
|
* Provides multi-tenant aware CRUD operations using TypeORM.
|
|
* All domain services should extend this base class.
|
|
*
|
|
* @module @shared/services
|
|
*/
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.BaseService = void 0;
|
|
class BaseService {
|
|
repository;
|
|
constructor(repository) {
|
|
this.repository = repository;
|
|
}
|
|
/**
|
|
* Find all records for a tenant with optional pagination
|
|
*/
|
|
async findAll(ctx, options) {
|
|
const page = options?.page || 1;
|
|
const limit = options?.limit || 20;
|
|
const skip = (page - 1) * limit;
|
|
const where = {
|
|
tenantId: ctx.tenantId,
|
|
deletedAt: null,
|
|
...options?.where,
|
|
};
|
|
const [data, total] = await this.repository.findAndCount({
|
|
where,
|
|
take: limit,
|
|
skip,
|
|
order: { createdAt: 'DESC' },
|
|
});
|
|
return {
|
|
data,
|
|
meta: {
|
|
total,
|
|
page,
|
|
limit,
|
|
totalPages: Math.ceil(total / limit),
|
|
},
|
|
};
|
|
}
|
|
/**
|
|
* Find one record by ID for a tenant
|
|
*/
|
|
async findById(ctx, id) {
|
|
return this.repository.findOne({
|
|
where: {
|
|
id,
|
|
tenantId: ctx.tenantId,
|
|
deletedAt: null,
|
|
},
|
|
});
|
|
}
|
|
/**
|
|
* Find one record by criteria
|
|
*/
|
|
async findOne(ctx, where) {
|
|
return this.repository.findOne({
|
|
where: {
|
|
tenantId: ctx.tenantId,
|
|
deletedAt: null,
|
|
...where,
|
|
},
|
|
});
|
|
}
|
|
/**
|
|
* Find records by custom options
|
|
*/
|
|
async find(ctx, options) {
|
|
return this.repository.find({
|
|
...options,
|
|
where: {
|
|
tenantId: ctx.tenantId,
|
|
deletedAt: null,
|
|
...(options.where || {}),
|
|
},
|
|
});
|
|
}
|
|
/**
|
|
* Create a new record
|
|
*/
|
|
async create(ctx, data) {
|
|
const entity = this.repository.create({
|
|
...data,
|
|
tenantId: ctx.tenantId,
|
|
createdById: ctx.userId,
|
|
});
|
|
return this.repository.save(entity);
|
|
}
|
|
/**
|
|
* Update an existing record
|
|
*/
|
|
async update(ctx, id, data) {
|
|
const existing = await this.findById(ctx, id);
|
|
if (!existing) {
|
|
return null;
|
|
}
|
|
const updated = this.repository.merge(existing, {
|
|
...data,
|
|
updatedById: ctx.userId,
|
|
});
|
|
return this.repository.save(updated);
|
|
}
|
|
/**
|
|
* Soft delete a record
|
|
*/
|
|
async softDelete(ctx, id) {
|
|
const existing = await this.findById(ctx, id);
|
|
if (!existing) {
|
|
return false;
|
|
}
|
|
await this.repository.update({ id, tenantId: ctx.tenantId }, {
|
|
deletedAt: new Date(),
|
|
deletedById: ctx.userId,
|
|
});
|
|
return true;
|
|
}
|
|
/**
|
|
* Hard delete a record (use with caution)
|
|
*/
|
|
async hardDelete(ctx, id) {
|
|
const result = await this.repository.delete({
|
|
id,
|
|
tenantId: ctx.tenantId,
|
|
});
|
|
return (result.affected ?? 0) > 0;
|
|
}
|
|
/**
|
|
* Count records
|
|
*/
|
|
async count(ctx, where) {
|
|
return this.repository.count({
|
|
where: {
|
|
tenantId: ctx.tenantId,
|
|
deletedAt: null,
|
|
...where,
|
|
},
|
|
});
|
|
}
|
|
/**
|
|
* Check if a record exists
|
|
*/
|
|
async exists(ctx, where) {
|
|
const count = await this.count(ctx, where);
|
|
return count > 0;
|
|
}
|
|
}
|
|
exports.BaseService = BaseService;
|
|
//# sourceMappingURL=base.service.js.map
|