@opra/sqb
Version:
Opra SQB adapter package
309 lines (308 loc) • 10.1 kB
JavaScript
import { ResourceNotAvailableError } from '@opra/common';
import { SQBAdapter } from './sqb-adapter.js';
import { SqbEntityService } from './sqb-entity-service.js';
/**
* Service for managing a collection of entities backed by an SQB data source.
*
* @typeParam T - The entity type managed by this service
*/
export class SqbCollectionService extends SqbEntityService {
/**
* Default maximum number of records returned by `findMany`.
*/
defaultLimit;
/**
* Constructs a new instance.
*
* @param dataType - The data type of the collection elements.
* @param options - Options for the collection service.
*/
constructor(dataType, options) {
super(dataType, options);
this.defaultLimit = options?.defaultLimit || 100;
}
/**
* Asserts that a resource with the given ID exists.
* Throws {@link ResourceNotAvailableError} if it does not.
*
* @param id - The ID of the resource to check.
* @param options - Optional existence check options.
* @throws {@link ResourceNotAvailableError} If the resource does not exist.
*/
async assert(id, options) {
if (!(await this.exists(id, options)))
throw new ResourceNotAvailableError(this.getResourceName(), id);
}
async create(input, options) {
const command = {
crud: 'create',
method: 'create',
byId: false,
input,
options,
};
return this._executeCommand(command, () => this._create(command));
}
/**
* Creates a new resource without returning it.
*
* @param input - The input data for the new resource.
* @param options - Optional create options.
*/
async createOnly(input, options) {
const command = {
crud: 'create',
method: 'createOnly',
byId: false,
input,
options,
};
return this._executeCommand(command, () => this._createOnly(command));
}
/**
* Returns the number of records matching the given options.
*
* @param options - Options for the count operation.
* @returns The number of matching records.
*/
async count(options) {
const command = {
crud: 'read',
method: 'count',
byId: false,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._count(command);
});
}
/**
* Deletes the record with the given ID.
*
* @param id - The ID of the record to delete.
* @param options - Optional delete options.
* @returns The number of records deleted.
*/
async delete(id, options) {
const command = {
crud: 'delete',
method: 'delete',
byId: true,
documentId: id,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._delete(command);
});
}
/**
* Deletes all records matching the given options.
*
* @param options - Options including filter criteria.
* @returns The number of records deleted.
*/
async deleteMany(options) {
const command = {
crud: 'delete',
method: 'deleteMany',
byId: false,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._deleteMany(command);
});
}
/**
* Checks whether a record with the given ID exists.
*
* @param id - The ID to check.
* @param options - Optional query options.
* @returns `true` if the record exists, `false` otherwise.
*/
async exists(id, options) {
const command = {
crud: 'read',
method: 'exists',
byId: true,
documentId: id,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._exists(command);
});
}
/**
* Checks whether any record matching the given options exists.
*
* @param options - Optional query options.
* @returns `true` if at least one matching record exists, `false` otherwise.
*/
async existsOne(options) {
const command = {
crud: 'read',
method: 'existsOne',
byId: false,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._existsOne(command);
});
}
async findById(id, options) {
const command = {
crud: 'read',
method: 'findById',
byId: true,
documentId: id,
options,
};
return this._executeCommand(command, async () => {
const documentFilter = await this._getCommonFilter(command);
const filter = SQBAdapter.prepareFilter([
documentFilter,
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._findById(command);
});
}
async findOne(options) {
const command = {
crud: 'read',
method: 'findOne',
byId: false,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._findOne(command);
});
}
async findMany(options) {
const command = {
crud: 'read',
method: 'findMany',
byId: false,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
const limit = command.options?.limit || this.defaultLimit;
command.options = { ...command.options, filter, limit };
return this._findMany(command);
});
}
async findManyWithCount(options) {
const [items, count] = await Promise.all([
this.findMany(options),
this.count(options),
]);
return { count, items };
}
async get(id, options) {
const out = await this.findById(id, options);
if (!out)
throw new ResourceNotAvailableError(this.getResourceName(), id);
return out;
}
async update(id, input, options) {
const command = {
crud: 'update',
method: 'update',
documentId: id,
byId: true,
input,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._update(command);
});
}
/**
* Updates a record by ID without returning it.
*
* @param id - The ID of the record to update.
* @param input - The fields to update.
* @param options - Optional update options.
* @returns The number of records modified.
*/
async updateOnly(id, input, options) {
const command = {
crud: 'update',
method: 'update',
documentId: id,
byId: true,
input,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._updateOnly(command);
});
}
/**
* Updates all records matching the given options.
*
* @param input - The fields to update.
* @param options - Options including filter criteria.
* @returns The number of records modified.
*/
async updateMany(input, options) {
const command = {
crud: 'update',
method: 'updateMany',
byId: false,
input,
options,
};
return this._executeCommand(command, async () => {
const filter = SQBAdapter.prepareFilter([
await this._getCommonFilter(command),
command.options?.filter,
]);
command.options = { ...command.options, filter };
return this._updateMany(command);
});
}
}