@opra/sqb
Version:
Opra SQB adapter package
174 lines (173 loc) • 5.77 kB
JavaScript
import { ResourceNotAvailableError } from '@opra/common';
import { EntityMetadata } from '@sqb/connect';
import { SQBAdapter } from './sqb-adapter.js';
import { SqbEntityService } from './sqb-entity-service.js';
/**
* Service for managing a single entity record backed by an SQB data source.
*
* @typeParam T - The entity type managed by this service
*/
export class SqbSingletonService extends SqbEntityService {
/**
* The identifier used to locate the singleton record.
*/
id;
/**
* Constructs a new instance.
*
* @param dataType - The entity class or its registered name.
* @param options - Options for the singleton service.
*/
constructor(dataType, options) {
super(dataType, options);
this.id = options?.id || 1;
}
/**
* Asserts that the singleton record exists.
* Throws {@link ResourceNotAvailableError} if it does not.
*
* @param options - Optional existence check options.
* @throws {@link ResourceNotAvailableError} If the record does not exist.
*/
async assert(options) {
if (!(await this.exists(options)))
throw new ResourceNotAvailableError(this.getResourceName());
}
async create(input, options) {
const command = {
crud: 'create',
method: 'create',
byId: false,
input,
options,
};
return this._executeCommand(command, async () => {
const primaryFields = EntityMetadata.getPrimaryIndexColumns(this.entityMetadata);
const data = { ...command.input };
if (primaryFields.length > 1) {
if (typeof primaryFields !== 'object') {
throw new TypeError(`"${this.entityMetadata.name}" should has multiple primary key fields. So you should provide and object that contains key fields`);
}
for (const field of primaryFields) {
data[field.name] = this.id[field.name];
}
}
else
data[primaryFields[0].name] = this.id;
command.input = data;
return await this._create(command);
});
}
/**
* Deletes the singleton record.
*
* @param options - Optional delete options.
* @returns The number of records deleted.
*/
async delete(options) {
const command = {
crud: 'delete',
method: 'delete',
byId: true,
documentId: this.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);
});
}
/**
* Checks whether the singleton record exists.
*
* @param options - Optional query options.
* @returns `true` if the record exists, `false` otherwise.
*/
async exists(options) {
const command = {
crud: 'read',
method: 'exists',
byId: true,
documentId: this.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);
});
}
async find(options) {
const command = {
crud: 'read',
method: 'findById',
byId: true,
documentId: this.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._findById(command);
});
}
async get(options) {
const out = await this.find(options);
if (!out)
throw new ResourceNotAvailableError(this.getResourceName());
return out;
}
async update(input, options) {
const command = {
crud: 'update',
method: 'update',
documentId: this.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 the singleton record without returning it.
*
* @param input - The fields to update.
* @param options - Optional update options.
* @returns The number of records modified.
*/
async updateOnly(input, options) {
const command = {
crud: 'update',
method: 'update',
documentId: this.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);
});
}
}