@opra/sqb
Version:
Opra SQB adapter package
432 lines (431 loc) • 17.1 kB
TypeScript
import { ComplexType } from '@opra/common';
import { ExecutionContext, ServiceBase } from '@opra/core';
import { SqlElement } from '@sqb/builder';
import { EntityMetadata, Repository } from '@sqb/connect';
import type { Nullish, PartialDTO, PatchDTO, RequiredSome, StrictOmit, Type } from 'ts-gems';
import { vg } from 'valgen';
import { SQBAdapter } from './sqb-adapter.js';
import { SqbServiceBase } from './sqb-service-base.js';
/**
* Namespace containing types and options for SqbEntityService.
*/
export declare namespace SqbEntityService {
/**
* Configuration options for SqbEntityService.
*/
interface Options extends SqbServiceBase.Options {
/**
* The name of the resource managed by this service.
*/
resourceName?: SqbEntityService<any>['resourceName'];
/**
* Optional error handler.
*/
onError?: SqbEntityService<any>['onError'];
/**
* Optional common filter applied to all read/write operations.
*/
commonFilter?: SqbEntityService<any>['commonFilter'];
/**
* Optional interceptor for the service operations.
*/
interceptor?: SqbEntityService<any>['interceptor'];
/**
* Optional scope for the service.
*/
scope?: SqbEntityService<any>['scope'];
}
/**
* Represents the CRUD operation types.
*/
type CrudOp = 'create' | 'read' | 'update' | 'delete';
/**
* Information about the command being executed.
*/
interface CommandInfo {
crud: SqbEntityService.CrudOp;
method: string;
byId: boolean;
documentId?: SQBAdapter.IdOrIds;
input?: Record<string, any>;
options?: Record<string, any>;
}
/**
* Type definition for a common filter.
*/
type CommonFilter = SQBAdapter.FilterInput | ((args: SqbEntityService.CommandInfo, _this: SqbEntityService<any>) => SQBAdapter.FilterInput | Promise<SQBAdapter.FilterInput> | undefined);
interface CreateOptions extends Repository.CreateOptions {
}
interface CountOptions extends StrictOmit<Repository.CountOptions, 'filter'> {
filter?: Repository.CountOptions['filter'] | string;
}
interface DeleteOptions extends StrictOmit<Repository.DeleteOptions, 'filter'> {
filter?: Repository.DeleteOptions['filter'] | string;
}
interface DeleteManyOptions extends StrictOmit<Repository.DeleteManyOptions, 'filter'> {
filter?: Repository.DeleteManyOptions['filter'] | string;
}
interface ExistsOptions extends StrictOmit<Repository.ExistsOptions, 'filter'> {
filter?: Repository.ExistsOptions['filter'] | string;
}
interface FindOneOptions extends StrictOmit<Repository.FindOneOptions, 'filter' | 'offset'> {
filter?: Repository.FindOneOptions['filter'] | string;
skip?: number;
}
interface FindManyOptions extends StrictOmit<Repository.FindManyOptions, 'filter' | 'offset'> {
filter?: Repository.FindManyOptions['filter'] | string;
skip?: number;
}
interface UpdateOneOptions extends StrictOmit<Repository.UpdateOptions, 'filter'> {
filter?: Repository.UpdateOptions['filter'] | string;
}
interface UpdateManyOptions extends StrictOmit<Repository.UpdateManyOptions, 'filter'> {
filter?: Repository.UpdateManyOptions['filter'] | string;
}
interface CreateCommand<T> extends StrictOmit<RequiredSome<CommandInfo, 'input'>, 'documentId'> {
crud: 'create';
input: PatchDTO<T>;
options?: CreateOptions;
}
interface CountCommand extends StrictOmit<CommandInfo, 'documentId' | 'input'> {
crud: 'read';
options?: CountOptions;
}
interface DeleteOneCommand extends StrictOmit<CommandInfo, 'input'> {
crud: 'delete';
options?: DeleteOptions;
}
interface DeleteManyCommand extends StrictOmit<CommandInfo, 'input'> {
crud: 'delete';
options?: DeleteManyOptions;
}
interface ExistsCommand extends StrictOmit<CommandInfo, 'input'> {
crud: 'read';
options?: ExistsOptions;
}
interface FindOneCommand extends StrictOmit<CommandInfo, 'input'> {
crud: 'read';
options?: FindOneOptions;
}
interface FindManyCommand extends StrictOmit<CommandInfo, 'input'> {
crud: 'read';
options?: FindManyOptions;
}
interface UpdateOneCommand<T> extends CommandInfo {
crud: 'update';
input: PatchDTO<T, SqlElement>;
options?: UpdateOneOptions;
}
interface UpdateManyCommand<T> extends CommandInfo {
crud: 'update';
input: PatchDTO<T, SqlElement>;
options?: UpdateManyOptions;
}
}
export interface SqbEntityService {
/**
* Optional interceptor that wraps every command execution.
*
* @param next - Calls the next interceptor or the actual command handler.
* @param command - Metadata describing the current operation.
* @param _this - Reference to the service instance.
* @returns The result of the command execution.
*/
interceptor?(next: () => any, command: SqbEntityService.CommandInfo, _this: any): Promise<any>;
}
/**
* Base service providing CRUD operations over an SQB entity.
*
* @typeParam T - The entity type managed by this service
*/
export declare class SqbEntityService<T extends object = object> extends SqbServiceBase {
protected _dataTypeScope?: string;
protected _dataType_: Type | string;
protected _dataType?: ComplexType;
protected _dataTypeClass?: Type;
protected _entityMetadata?: EntityMetadata;
protected _inputCodecs: Record<string, vg.isObject.Validator<T>>;
protected _outputCodecs: Record<string, vg.isObject.Validator<T>>;
/**
* Comma-delimited scopes used to filter the API document.
*/
scope?: string;
/**
* Override for the resource name exposed in error messages and API metadata.
* Accepts a static string or a function that returns one.
*/
resourceName?: string | ((_this: this) => string);
/**
* Filter(s) automatically applied to every query for this service.
* Useful for multi-tenant isolation or other cross-cutting constraints.
*/
commonFilter?: SqbEntityService.CommonFilter | SqbEntityService.CommonFilter[];
/**
* Called whenever a command throws. Useful for logging or transforming errors.
*
* @param error - The thrown error.
* @param command - The service command during which the error was thrown.
* @param _this - The service instance.
*/
onError?: (error: unknown, command: SqbEntityService.CommandInfo, _this: any) => void | Promise<void>;
/**
* Constructs a new instance.
*
* @param dataType - The entity class or its registered name.
* @param options - Options for the service.
*/
constructor(dataType: Type<T> | string, options?: SqbEntityService.Options);
/**
* Returns the resolved OPRA `ComplexType` for this service's entity.
*
* @throws If the data type is not registered as a `ComplexType`.
*/
get dataType(): ComplexType;
/**
* Returns the constructor class of the entity data type.
*
* @throws If the data type is not registered as a `ComplexType`.
*/
get dataTypeClass(): Type;
/**
* Returns the SQB `EntityMetadata` for the entity class.
*
* @throws If the class is not decorated with `@Entity()`.
*/
get entityMetadata(): EntityMetadata;
for<C extends ExecutionContext, P extends Partial<this>>(context: C | ServiceBase, overwriteProperties?: Nullish<P>, overwriteContext?: Partial<C>): this & Required<P>;
/**
* Returns the resource name used in error messages and API metadata.
*
* @throws If neither `resourceName` nor the data type name is available.
*/
getResourceName(): string;
/**
* Returns the input codec for the given operation (e.g. `'create'`, `'update'`).
*
* @param operation - The operation name.
*/
getInputCodec(operation: string): vg.isObject.Validator<T>;
/**
* Returns the output codec for the given operation.
*
* @param operation - The operation name.
*/
getOutputCodec(operation: string): vg.isObject.Validator<T>;
/**
* Inserts a new record into the database and returns the created document.
*
* @param command - The create command.
* @returns The created document.
* @protected
*/
protected _create(command: SqbEntityService.CreateCommand<T>): Promise<PartialDTO<T>>;
/**
* Inserts a new record into the database without returning it.
*
* @param command - The create command.
* @protected
*/
protected _createOnly(command: SqbEntityService.CreateCommand<T>): Promise<any>;
/**
* Returns the count of records matching the command options.
*
* @param command - The count command.
* @protected
*/
protected _count(command: SqbEntityService.CountCommand): Promise<number>;
/**
* Deletes the record identified by `command.documentId`.
*
* @param command - The delete command.
* @returns The number of records deleted.
* @protected
*/
protected _delete(command: SqbEntityService.DeleteOneCommand): Promise<number>;
/**
* Deletes all records matching the command filter.
*
* @param command - The deleteMany command.
* @returns The number of records deleted.
* @protected
*/
protected _deleteMany(command: SqbEntityService.DeleteManyCommand): Promise<number>;
/**
* Checks whether the record identified by `command.documentId` exists.
*
* @param command - The exists command.
* @protected
*/
protected _exists(command: SqbEntityService.ExistsCommand): Promise<boolean>;
/**
* Checks whether any record matching the command filter exists.
*
* @param command - The existsOne command.
* @protected
*/
protected _existsOne(command: SqbEntityService.ExistsCommand): Promise<boolean>;
/**
* Finds the record identified by `command.documentId`.
*
* @param command - The findById command.
* @returns The found record, or `undefined` if not found.
* @protected
*/
protected _findById(command: SqbEntityService.FindOneCommand): Promise<PartialDTO<T> | undefined>;
/**
* Finds the first record matching the command filter.
*
* @param command - The findOne command.
* @returns The found record, or `undefined` if not found.
* @protected
*/
protected _findOne(command: SqbEntityService.FindOneCommand): Promise<PartialDTO<T> | undefined>;
/**
* Finds all records matching the command filter.
*
* @param command - The findMany command.
* @returns An array of matching records.
* @protected
*/
protected _findMany(command: SqbEntityService.FindManyCommand): Promise<PartialDTO<T>[]>;
/**
* Updates the record identified by `command.documentId` and returns it.
*
* @param command - The update command.
* @returns The updated record, or `undefined` if not found.
* @protected
*/
protected _update(command: SqbEntityService.UpdateOneCommand<T>): Promise<PartialDTO<T> | undefined>;
/**
* Updates the record identified by `command.documentId` without returning it.
*
* @param command - The updateOnly command.
* @returns The number of records modified.
* @protected
*/
protected _updateOnly(command: SqbEntityService.UpdateOneCommand<T>): Promise<number>;
/**
* Updates all records matching the command filter.
*
* @param command - The updateMany command.
* @returns The number of records modified.
* @protected
*/
protected _updateMany(command: SqbEntityService.UpdateOneCommand<T>): Promise<number>;
/**
* Acquires a connection and performs `Repository.create`.
*
* @param input - The document to insert.
* @param options - Optional settings.
* @protected
*/
protected _dbCreate(input: PartialDTO<T>, options?: Repository.CreateOptions): Promise<PartialDTO<T>>;
/**
* Acquires a connection and performs `Repository.count`.
*
* @param options - Optional settings.
* @protected
*/
protected _dbCount(options?: Repository.CountOptions): Promise<number>;
/**
* Acquires a connection and performs `Repository.delete`.
*
* @param id - The key field value identifying the record.
* @param options - Optional settings.
* @protected
*/
protected _dbDelete(id: SQBAdapter.IdOrIds, options?: Repository.DeleteOptions): Promise<number>;
/**
* Acquires a connection and performs `Repository.deleteMany`.
*
* @param options - Optional settings.
* @protected
*/
protected _dbDeleteMany(options?: Repository.DeleteManyOptions): Promise<number>;
/**
* Acquires a connection and performs `Repository.exists`.
*
* @param id - The key field value identifying the record.
* @param options - Optional settings.
* @protected
*/
protected _dbExists(id: SQBAdapter.IdOrIds, options?: Repository.ExistsOptions): Promise<boolean>;
/**
* Acquires a connection and performs `Repository.existsOne`.
*
* @param options - Optional settings.
* @protected
*/
protected _dbExistsOne(options?: Repository.ExistsOptions): Promise<boolean>;
/**
* Acquires a connection and performs `Repository.findById`.
*
* @param id - The key field value identifying the record.
* @param options - Optional settings.
* @protected
*/
protected _dbFindById(id: SQBAdapter.IdOrIds, options?: Repository.FindOptions): Promise<PartialDTO<T> | undefined>;
/**
* Acquires a connection and performs `Repository.findOne`.
*
* @param options - Optional settings.
* @protected
*/
protected _dbFindOne(options?: StrictOmit<Repository.FindOneOptions, 'offset'> & {
skip?: number;
}): Promise<PartialDTO<T> | undefined>;
/**
* Acquires a connection and performs `Repository.findMany`.
*
* @param options - Optional settings.
* @protected
*/
protected _dbFindMany(options?: StrictOmit<Repository.FindManyOptions, 'offset'> & {
skip?: number;
}): Promise<PartialDTO<T>[]>;
/**
* Acquires a connection and performs `Repository.update`.
*
* @param id - The key field value identifying the record.
* @param data - The update values.
* @param options - Optional settings.
* @protected
*/
protected _dbUpdate(id: SQBAdapter.IdOrIds, data: PatchDTO<T>, options?: Repository.UpdateOptions): Promise<PartialDTO<T> | undefined>;
/**
* Acquires a connection and performs `Repository.updateOnly`.
*
* @param id - The key field value identifying the record.
* @param data - The update values.
* @param options - Optional settings.
* @protected
*/
protected _dbUpdateOnly(id: SQBAdapter.IdOrIds, data: PatchDTO<T>, options?: Repository.UpdateOptions): Promise<number>;
/**
* Acquires a connection and performs `Repository.updateMany`.
*
* @param data - The update values.
* @param options - Optional settings.
* @protected
*/
protected _dbUpdateMany(data: PatchDTO<T>, options?: Repository.UpdateManyOptions): Promise<number>;
/**
* Builds the common filter for the given command.
* Used primarily for multi-tenant isolation and similar cross-cutting concerns.
*
* @protected
* @returns The resolved filter input, or `undefined` if none is configured.
*/
protected _getCommonFilter(command: SqbEntityService.CommandInfo): SQBAdapter.FilterInput | Promise<SQBAdapter.FilterInput> | undefined;
protected _executeCommand(command: SqbEntityService.CommandInfo, commandFn: () => any): Promise<any>;
protected _beforeCreate(command: SqbEntityService.CreateCommand<T>): Promise<void>;
protected _beforeUpdate(command: SqbEntityService.UpdateOneCommand<T>): Promise<void>;
protected _beforeUpdateMany(command: SqbEntityService.UpdateManyCommand<T>): Promise<void>;
protected _beforeDelete(command: SqbEntityService.DeleteOneCommand): Promise<void>;
protected _beforeDeleteMany(command: SqbEntityService.DeleteManyCommand): Promise<void>;
protected _afterCreate(command: SqbEntityService.CreateCommand<T>, result: PartialDTO<T>): Promise<void>;
protected _afterUpdate(command: SqbEntityService.UpdateOneCommand<T>, result?: PartialDTO<T>): Promise<void>;
protected _afterUpdateMany(command: SqbEntityService.UpdateManyCommand<T>, affected: number): Promise<void>;
protected _afterDelete(command: SqbEntityService.DeleteOneCommand, affected: number): Promise<void>;
protected _afterDeleteMany(command: SqbEntityService.DeleteManyCommand, affected: number): Promise<void>;
}