UNPKG

@opra/sqb

Version:

Opra SQB adapter package

174 lines (173 loc) 5.77 kB
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); }); } }