refactor: ajustar importaciones y tipos en varios archivos para mejorar la claridad y la consistencia

This commit is contained in:
David Arranz 2026-09-07 18:55:11 +02:00
parent 2f23d75b6f
commit 38fb6299b7
12 changed files with 260 additions and 76 deletions

View File

@ -1,8 +1,8 @@
import type { ISequelizeTransactionContext } from "@erp/core/api"; import type { ISequelizeTransactionContext } from "@erp/core/api";
import type { AuditEntry, AuditRecordOptions, IAuditStore } from "@repo/rdx-audit"; import type { AuditEntry, IAuditStore } from "@repo/rdx-audit";
import { AuditStoreError } from "@repo/rdx-audit"; import { type AuditRecordOptions, AuditStoreError } from "@repo/rdx-audit";
import { Result } from "@repo/rdx-utils"; import { Result } from "@repo/rdx-utils";
import type { ModelStatic } from "sequelize"; import type { ModelStatic, Transaction } from "sequelize";
import type { AuditChangeModel } from "./audit-change.model"; import type { AuditChangeModel } from "./audit-change.model";
import type { AuditEventModel } from "./audit-event.model"; import type { AuditEventModel } from "./audit-event.model";
@ -19,8 +19,12 @@ export class SequelizeAuditStore implements IAuditStore {
private readonly transactionContext: ISequelizeTransactionContext private readonly transactionContext: ISequelizeTransactionContext
) {} ) {}
async append(entry: AuditEntry, options?: AuditRecordOptions): Promise<Result<void, AuditStoreError>> { async append(
const transaction = options?.transaction ?? this.transactionContext.current(); entry: AuditEntry,
options?: AuditRecordOptions
): Promise<Result<void, AuditStoreError>> {
const transaction = (options?.transaction as Transaction) ?? this.transactionContext.current();
if (entry.kind === "mutation" && !transaction) { if (entry.kind === "mutation" && !transaction) {
return Result.fail( return Result.fail(
new AuditStoreError("An active transaction is required for audit mutations.") new AuditStoreError("An active transaction is required for audit mutations.")

View File

@ -1,7 +1,7 @@
import type { AuditEntry, IAuditStore } from "@repo/rdx-audit"; import type { AuditEntry, AuditRecordOptions, IAuditStore } from "@repo/rdx-audit";
import { AuditStoreError } from "@repo/rdx-audit"; import { AuditStoreError } from "@repo/rdx-audit";
import { Result } from "@repo/rdx-utils"; import { Result } from "@repo/rdx-utils";
import type { ModelStatic } from "sequelize"; import type { ModelStatic, Transaction } from "sequelize";
import type { ISequelizeTransactionContext } from "../../persistence/sequelize"; import type { ISequelizeTransactionContext } from "../../persistence/sequelize";
@ -18,7 +18,7 @@ export class SequelizeAuditStore implements IAuditStore {
entry: AuditEntry, entry: AuditEntry,
options?: AuditRecordOptions options?: AuditRecordOptions
): Promise<Result<void, AuditStoreError>> { ): Promise<Result<void, AuditStoreError>> {
const transaction = options?.transaction ?? this.transactionContext.current(); const transaction = (options?.transaction as Transaction) ?? this.transactionContext.current();
if (entry.kind === "mutation" && !transaction) if (entry.kind === "mutation" && !transaction)
return Result.fail( return Result.fail(
new AuditStoreError("An active transaction is required for audit mutations.") new AuditStoreError("An active transaction is required for audit mutations.")

View File

@ -1,11 +1,5 @@
// core/api/infrastructure/documents/certificates/ import type { ICompanyCertificateContext, ISigningContextResolver } from "../../../application";
// env-company-signing-context-store.ts import type { ModuleParams } from "../../../modules";
import type {
ICompanyCertificateContext,
ISigningContextResolver,
} from "@erp/core/api/application";
import type { ModuleParams } from "@erp/core/api/modules";
import type { ICompanySigningContextRecord } from "./company-signing-context-record.interface"; import type { ICompanySigningContextRecord } from "./company-signing-context-record.interface";

View File

@ -1,5 +1,4 @@
import type { IDocumentSigningService } from "@erp/core/api/application"; import type { ICompanyCertificateContext, IDocumentSigningService } from "../../../application";
import type { ICompanyCertificateContext } from "@erp/core/api/application/documents/application-models/company-certificate-context.interface";
import type { RestDocumentSigningConfig } from "./rest-document-signing-config"; import type { RestDocumentSigningConfig } from "./rest-document-signing-config";
import { SimpleCircuitBreaker } from "./simple-circuit-breaker"; import { SimpleCircuitBreaker } from "./simple-circuit-breaker";

View File

@ -1,4 +1,4 @@
import type { DomainMapperWithBulk, IQueryMapperWithBulk } from "@erp/core/api/application"; import type { DomainMapperWithBulk, IQueryMapperWithBulk } from "../../../../application";
export interface ISequelizeDomainMapper<TModel, TModelAttributes, TEntity> export interface ISequelizeDomainMapper<TModel, TModelAttributes, TEntity>
extends DomainMapperWithBulk<TModel | TModelAttributes, TEntity> {} extends DomainMapperWithBulk<TModel | TModelAttributes, TEntity> {}

View File

@ -1,4 +1,4 @@
export * from "./module-server.interface";
export * from "./module-runtime"; export * from "./module-runtime";
export * from "./module-server.interface";
export * from "./modules-runtime"; export * from "./modules-runtime";
export * from "./types"; export * from "./types";

View File

@ -1,11 +1,11 @@
import type { ILogger } from "@repo/rdx-logger"; import type { ILogger } from "@repo/rdx-logger";
import type { ModelStatic, Sequelize } from "sequelize"; import type { Model, ModelStatic, Sequelize } from "sequelize";
import type { IModuleServer } from "./module-server.interface"; import type { IModuleServer } from "./module-server.interface";
import type { ModuleParams, ModuleSetupResult, StartParams, WarmupParams } from "./types";
import type { ModulesRuntime } from "./modules-runtime"; import type { ModulesRuntime } from "./modules-runtime";
import type { ModuleParams, ModuleSetupResult, StartParams, WarmupParams } from "./types";
type ModelInitializer = (database: Sequelize) => ModelStatic; type ModelInitializer = (database: Sequelize) => ModelStatic<Model>;
type ModelEntry = { initializer: ModelInitializer; moduleName: string }; type ModelEntry = { initializer: ModelInitializer; moduleName: string };
const modules = new Map<string, IModuleServer>(); const modules = new Map<string, IModuleServer>();
@ -29,13 +29,28 @@ export function registerModels(initializers: ModelInitializer[], moduleName: str
} }
/** Inicializa únicamente infraestructura backend: setup, modelos y warmups. */ /** Inicializa únicamente infraestructura backend: setup, modelos y warmups. */
export async function initModules(params: ModuleParams & { logger: ILogger; database: Sequelize; warmup: { timeoutMs: number; strict: boolean }; databaseSyncMode: string }): Promise<ModulesRuntime> { export async function initModules(
params: ModuleParams & {
logger: ILogger;
database: Sequelize;
warmup: { timeoutMs: number; strict: boolean };
databaseSyncMode: string;
}
): Promise<ModulesRuntime> {
for (const name of modules.keys()) await setupModule(name, params, []); for (const name of modules.keys()) await setupModule(name, params, []);
await initializeModels(params.database, params.databaseSyncMode, params.logger); await initializeModels(params.database, params.databaseSyncMode, params.logger);
await warmupModules(params); await warmupModules(params);
validateDependencies(); validateDependencies();
const customerInvoices = internals.get("customer-invoices") as { proformas: { recurringProformas: ModulesRuntime["customerInvoices"]["recurringProformas"] } } | undefined;
if (!customerInvoices) throw new Error('Module "customer-invoices" did not expose recurring runtime capabilities'); const customerInvoices = internals.get("customer-invoices") as
| {
proformas: { recurringProformas: ModulesRuntime["customerInvoices"]["recurringProformas"] };
}
| undefined;
if (!customerInvoices)
throw new Error('Module "customer-invoices" did not expose recurring runtime capabilities');
return { customerInvoices: customerInvoices.proformas.recurringProformas }; return { customerInvoices: customerInvoices.proformas.recurringProformas };
} }
@ -44,71 +59,228 @@ export async function startModules(params: ModuleParams & { logger: ILogger }):
for (const name of setupOrder) { for (const name of setupOrder) {
const module = modules.get(name); const module = modules.get(name);
if (!module?.start) continue; if (!module?.start) continue;
await module.start({ ...params, getService: makeGetService(name, module), getInternal: makeGetInternal(name), listServices } as StartParams); await module.start({
...params,
getService: makeGetService(name, module),
getInternal: makeGetInternal(name),
listServices,
} as StartParams);
} }
validateDependencies(); validateDependencies();
} }
async function setupModule(name: string, params: ModuleParams & { logger: ILogger }, stack: string[]): Promise<void> { async function setupModule(
if (setupDone.has(name)) return; name: string,
if (visiting.has(name)) throw new Error(`Cyclic dependency detected: ${[...stack, name].join(" -> ")}`); params: ModuleParams & { logger: ILogger },
stack: string[]
): Promise<void> {
if (setupDone.has(name)) {
return;
}
if (visiting.has(name)) {
throw new Error(`Cyclic dependency detected: ${[...stack, name].join(" -> ")}`);
}
const module = modules.get(name); const module = modules.get(name);
if (!module) throw new Error(`Module "${name}" not found`);
if (!module) {
throw new Error(`Module "${name}" not found`);
}
visiting.add(name); visiting.add(name);
for (const dependency of module.dependencies ?? []) await setupModule(dependency, params, [...stack, name]); for (const dependency of module.dependencies ?? []) {
const result = (await module.setup?.({ ...params, getService: makeGetService(name, module), listServices })) as ModuleSetupResult | undefined; await setupModule(dependency, params, [...stack, name]);
}
const result = (await module.setup?.({
...params,
getService: makeGetService(name, module),
listServices,
})) as ModuleSetupResult | undefined;
internals.set(name, result?.internal ?? {}); internals.set(name, result?.internal ?? {});
if (result?.models) registerModels(result.models as ModelInitializer[], name);
for (const [key, service] of Object.entries(result?.services ?? {})) registerService(`${name}:${key}`, service); if (result?.models) {
registerModels(result.models as ModelInitializer[], name);
}
for (const [key, service] of Object.entries(result?.services ?? {})) {
registerService(`${name}:${key}`, service);
}
setupDone.add(name); setupDone.add(name);
setupOrder.push(name); setupOrder.push(name);
visiting.delete(name); visiting.delete(name);
} }
async function initializeModels(database: Sequelize, syncMode: string, logger: ILogger): Promise<void> { async function initializeModels(
if (modelsInitialized) return; database: Sequelize,
const registered = new Map<string, { model: ModelStatic; moduleName: string }>(); syncMode: string,
logger: ILogger
): Promise<void> {
if (modelsInitialized) {
return;
}
const registered = new Map<string, { model: ModelStatic<Model>; moduleName: string }>();
for (const entry of models) { for (const entry of models) {
const model = entry.initializer(database); const model = entry.initializer(database);
if (!model?.name) throw new Error(`Invalid model initializer from "${entry.moduleName}"`); if (!model?.name) {
if (registered.has(model.name)) throw new Error(`Model name collision: "${model.name}"`); throw new Error(`Invalid model initializer from "${entry.moduleName}"`);
}
if (registered.has(model.name)) {
throw new Error(`Model name collision: "${model.name}"`);
}
registered.set(model.name, { model, moduleName: entry.moduleName }); registered.set(model.name, { model, moduleName: entry.moduleName });
} }
for (const { model } of registered.values()) { for (const { model } of registered.values()) {
const associate = model as ModelStatic & { associate?: (sequelize: Sequelize) => void }; const associate = model as ModelStatic<Model> & { associate?: (sequelize: Sequelize) => void };
associate.associate?.(database); associate.associate?.(database);
} }
if (syncMode === "alter") await database.sync({ force: false, alter: true });
if (syncMode === "force") await database.sync({ force: true, alter: false }); if (syncMode === "alter") {
logger.info("Backend module models initialized", { label: "moduleRuntime", modelCount: registered.size }); await database.sync({ force: false, alter: true });
}
if (syncMode === "force") {
await database.sync({ force: true, alter: false });
}
logger.info("Backend module models initialized", {
label: "moduleRuntime",
modelCount: registered.size,
});
modelsInitialized = true; modelsInitialized = true;
} }
async function warmupModules(params: ModuleParams & { logger: ILogger; warmup: { timeoutMs: number; strict: boolean } }): Promise<void> { async function warmupModules(
params: ModuleParams & { logger: ILogger; warmup: { timeoutMs: number; strict: boolean } }
): Promise<void> {
for (const name of setupOrder) { for (const name of setupOrder) {
const module = modules.get(name); const module = modules.get(name);
if (!module?.warmup) continue; if (!module?.warmup) continue;
try { try {
await withTimeout(Promise.resolve(module.warmup({ ...params, getService: makeGetService(name, module), getInternal: makeGetInternal(name), listServices } as WarmupParams)), params.warmup.timeoutMs, `${name}.warmup`); await withTimeout(
Promise.resolve(
module.warmup({
...params,
getService: makeGetService(name, module),
getInternal: makeGetInternal(name),
listServices,
} as WarmupParams)
),
params.warmup.timeoutMs,
`${name}.warmup`
);
} catch (error) { } catch (error) {
if (params.warmup.strict) throw error; if (params.warmup.strict) throw error;
params.logger.warn("Module warmup failed but continuing", { label: "moduleRuntime", module: name, error }); params.logger.warn("Module warmup failed but continuing", {
label: "moduleRuntime",
module: name,
error,
});
} }
} }
} }
function registerService(name: string, service: unknown): void { if (services[name]) throw new Error(`Service "${name}" already registered`); services[name] = service; } function registerService(name: string, service: unknown): void {
function makeGetService(moduleName: string, module: IModuleServer) { return <T>(name: string): T => { const [dependency, ...key] = name.split(":"); if (dependency !== "self") { if (!(module.dependencies ?? []).includes(dependency)) throw new Error(`Module "${moduleName}" tried to access service "${name}" without declaring dependency on "${dependency}"`); trackDependency(moduleName, dependency); return getService<T>(name); } return getService<T>(`${moduleName}:${key.join(":")}`); }; } if (services[name]) throw new Error(`Service "${name}" already registered`);
function makeGetInternal(moduleName: string) { return <T>(requestedModule: string, key?: string): T => { if (requestedModule !== moduleName) throw new Error(`Module "${moduleName}" attempted to access private internal state`); const internal = internals.get(moduleName) ?? {}; return (key ? internal[key] : internal) as T; }; } services[name] = service;
function getService<T>(name: string): T { const service = services[name]; if (!service) throw new Error(`Service "${name}" not found`); return service as T; } }
function trackDependency(moduleName: string, dependency: string): void { const used = usedDependencies.get(moduleName) ?? new Set<string>(); used.add(dependency); usedDependencies.set(moduleName, used); }
function validateDependencies(): void { for (const [name, module] of modules) { const declared = new Set(module.dependencies ?? []); const used = usedDependencies.get(name) ?? new Set<string>(); const undeclared = [...used].filter((dependency) => !declared.has(dependency)); if (undeclared.length) throw new Error(`Module "${name}" used undeclared dependencies: ${undeclared.join(", ")}`); } } function makeGetService(moduleName: string, module: IModuleServer) {
function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> { let timeout: NodeJS.Timeout | undefined; const timeoutPromise = new Promise<T>((_, reject) => { timeout = setTimeout(() => reject(new Error(`Timeout after ${timeoutMs}ms (${label})`)), timeoutMs); }); return Promise.race([promise, timeoutPromise]).finally(() => { if (timeout) clearTimeout(timeout); }) as Promise<T>; } return <T>(name: string): T => {
export function listServices(): string[] { return Object.keys(services); } const [dependency, ...key] = name.split(":");
export function getServiceScoped<T>(requesterModule: string, allowedDependencies: readonly string[], name: string): T { if (dependency !== "self") {
if (!(module.dependencies ?? []).includes(dependency))
throw new Error(
`Module "${moduleName}" tried to access service "${name}" without declaring dependency on "${dependency}"`
);
trackDependency(moduleName, dependency);
return getService<T>(name);
}
return getService<T>(`${moduleName}:${key.join(":")}`);
};
}
function makeGetInternal(moduleName: string) {
return <T>(requestedModule: string, key?: string): T => {
if (requestedModule !== moduleName)
throw new Error(`Module "${moduleName}" attempted to access private internal state`);
const internal = internals.get(moduleName) ?? {};
return (key ? internal[key] : internal) as T;
};
}
function getService<T>(name: string): T {
const service = services[name];
if (!service) throw new Error(`Service "${name}" not found`);
return service as T;
}
function trackDependency(moduleName: string, dependency: string): void {
const used = usedDependencies.get(moduleName) ?? new Set<string>();
used.add(dependency);
usedDependencies.set(moduleName, used);
}
function validateDependencies(): void {
for (const [name, module] of modules) {
const declared = new Set(module.dependencies ?? []);
const used = usedDependencies.get(name) ?? new Set<string>();
const undeclared = [...used].filter((dependency) => !declared.has(dependency));
if (undeclared.length)
throw new Error(`Module "${name}" used undeclared dependencies: ${undeclared.join(", ")}`);
}
}
function withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {
let timeout: NodeJS.Timeout | undefined;
const timeoutPromise = new Promise<T>((_, reject) => {
timeout = setTimeout(
() => reject(new Error(`Timeout after ${timeoutMs}ms (${label})`)),
timeoutMs
);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
if (timeout) clearTimeout(timeout);
}) as Promise<T>;
}
export function listServices(): string[] {
return Object.keys(services);
}
export function getServiceScoped<T>(
requesterModule: string,
allowedDependencies: readonly string[],
name: string
): T {
const [moduleName, ...key] = name.split(":"); const [moduleName, ...key] = name.split(":");
if (moduleName === "self") return getService<T>(`${requesterModule}:${key.join(":")}`); if (moduleName === "self") return getService<T>(`${requesterModule}:${key.join(":")}`);
if (!allowedDependencies.includes(moduleName)) throw new Error(`Module "${requesterModule}" tried to access service "${name}" without declaring dependency on "${moduleName}"`); if (!allowedDependencies.includes(moduleName))
throw new Error(
`Module "${requesterModule}" tried to access service "${name}" without declaring dependency on "${moduleName}"`
);
return getService<T>(name); return getService<T>(name);
} }
export function resetModuleRuntimeForTests(): void { modules.clear(); models.length = 0; setupOrder.length = 0; setupDone.clear(); visiting.clear(); internals.clear(); usedDependencies.clear(); for (const key of Object.keys(services)) delete services[key]; modelsInitialized = false; }
export function resetModuleRuntimeForTests(): void {
modules.clear();
models.length = 0;
setupOrder.length = 0;
setupDone.clear();
visiting.clear();
internals.clear();
usedDependencies.clear();
for (const key of Object.keys(services)) {
delete services[key];
}
modelsInitialized = false;
}

View File

@ -8,10 +8,17 @@ export interface RecurringProformaOccurrenceProcessorCapability {
} }
export interface RecurringProformaDiscoveryCapability { export interface RecurringProformaDiscoveryCapability {
findDue(dueThrough: Date, limit: number): Promise<{ findDue(
dueThrough: Date,
limit: number
): Promise<{
isFailure: boolean; isFailure: boolean;
error: Error; error: Error;
data: readonly { recurringProformaId: UniqueID; companyId: UniqueID; nextOccurrenceDate: Date }[]; data: readonly {
recurringProformaId: UniqueID;
companyId: UniqueID;
nextOccurrenceDate: Date;
}[];
}>; }>;
} }

View File

@ -1,8 +1,6 @@
import Dinero, { type Currency } from "dinero.js";
import type { MoneyDTO } from "../dto"; import type { MoneyDTO } from "../dto";
type DineroPlain = { amount: number; precision: number; currency: string }; //type DineroPlain = { amount: number; precision: number; currency: string };
const isEmptyMoneyDTO = (dto?: MoneyDTO | null) => const isEmptyMoneyDTO = (dto?: MoneyDTO | null) =>
!dto || dto.value?.trim?.() === "" || dto.scale?.trim?.() === ""; !dto || dto.value?.trim?.() === "" || dto.scale?.trim?.() === "";
@ -149,40 +147,40 @@ export const MoneyDTOHelper = {
/** /**
* Convierte un DTO a una instancia Dinero.js. * Convierte un DTO a una instancia Dinero.js.
*/ */
function dineroFromDTO(dto: MoneyDTO, fallbackCurrency = "EUR"): Dinero.Dinero { /*function dineroFromDTO(dto: MoneyDTO, fallbackCurrency = "EUR"): Dinero.Dinero {
const n = normalizeDTO(dto, fallbackCurrency); const n = normalizeDTO(dto, fallbackCurrency);
return Dinero({ return Dinero({
amount: Number.parseInt(n.value, 10), amount: Number.parseInt(n.value, 10),
precision: Number.parseInt(n.scale, 10), precision: Number.parseInt(n.scale, 10),
currency: n.currency_code as Currency, currency: n.currency_code as Currency,
}); });
} }*/
/** /**
* Convierte una instancia Dinero a un DTO. * Convierte una instancia Dinero a un DTO.
*/ */
function dtoFromDinero(d: Dinero.Dinero): MoneyDTO { /*function dtoFromDinero(d: Dinero.Dinero): MoneyDTO {
const { amount, precision, currency } = d.toObject() as DineroPlain; const { amount, precision, currency } = d.toObject() as DineroPlain;
return { return {
value: amount.toString(), value: amount.toString(),
scale: precision.toString(), scale: precision.toString(),
currency_code: currency, currency_code: currency,
}; };
} }*/
/** /**
* Suma una lista de MoneyDTO. * Suma una lista de MoneyDTO.
*/ */
function sumDTO(list: MoneyDTO[], fallbackCurrency = "EUR"): MoneyDTO { /*function sumDTO(list: MoneyDTO[], fallbackCurrency = "EUR"): MoneyDTO {
if (list.length === 0) return { value: "0", scale: "2", currency_code: fallbackCurrency }; if (list.length === 0) return { value: "0", scale: "2", currency_code: fallbackCurrency };
const sum = list.map((x) => dineroFromDTO(x, fallbackCurrency)).reduce((a, b) => a.add(b)); const sum = list.map((x) => dineroFromDTO(x, fallbackCurrency)).reduce((a, b) => a.add(b));
return dtoFromDinero(sum); return dtoFromDinero(sum);
} }*/
/** /**
* Multiplica un MoneyDTO por un número. * Multiplica un MoneyDTO por un número.
*/ */
function multiplyDTO( /*function multiplyDTO(
dto: MoneyDTO, dto: MoneyDTO,
multiplier: number, multiplier: number,
rounding: Dinero.RoundingMode = "HALF_EVEN", rounding: Dinero.RoundingMode = "HALF_EVEN",
@ -190,12 +188,12 @@ function multiplyDTO(
): MoneyDTO { ): MoneyDTO {
const d = dineroFromDTO(dto, fallbackCurrency).multiply(multiplier, rounding); const d = dineroFromDTO(dto, fallbackCurrency).multiply(multiplier, rounding);
return dtoFromDinero(d); return dtoFromDinero(d);
} }*/
/** /**
* Calcula un porcentaje de un MoneyDTO. * Calcula un porcentaje de un MoneyDTO.
*/ */
function percentageDTO( /*function percentageDTO(
dto: MoneyDTO, dto: MoneyDTO,
percent: number, percent: number,
rounding: Dinero.RoundingMode = "HALF_EVEN", rounding: Dinero.RoundingMode = "HALF_EVEN",
@ -203,4 +201,4 @@ function percentageDTO(
): MoneyDTO { ): MoneyDTO {
const d = dineroFromDTO(dto, fallbackCurrency).percentage(percent, rounding); const d = dineroFromDTO(dto, fallbackCurrency).percentage(percent, rounding);
return dtoFromDinero(d); return dtoFromDinero(d);
} }*/

View File

@ -1,5 +1,4 @@
export { Audit, type AuditDependencies } from "./audit"; export { Audit, type AuditDependencies } from "./audit";
export type { AuditArray, AuditObject, AuditScalar, AuditState, AuditValue } from "./audit-state.types";
export type { export type {
AuditActor, AuditActor,
AuditChange, AuditChange,
@ -11,6 +10,7 @@ export type {
AuditMutationEntry, AuditMutationEntry,
AuditMutationTarget, AuditMutationTarget,
AuditOperation, AuditOperation,
AuditRecordOptions,
AuditScope, AuditScope,
AuditSource, AuditSource,
IAudit, IAudit,
@ -22,6 +22,13 @@ export type {
RecordAuditMutationInput, RecordAuditMutationInput,
RecordAuditMutationShortcutInput, RecordAuditMutationShortcutInput,
} from "./audit.types"; } from "./audit.types";
export type {
AuditArray,
AuditObject,
AuditScalar,
AuditState,
AuditValue,
} from "./audit-state.types";
export { export {
AuditContextUnavailableError, AuditContextUnavailableError,
AuditError, AuditError,

View File

@ -75,7 +75,7 @@ export class CriteriaFromUrlConverter {
}); });
return Object.values(tempFilters).filter( return Object.values(tempFilters).filter(
(filter) => (filter): filter is FiltersPrimitives =>
filter.field !== undefined && filter.field !== undefined &&
filter.operator !== undefined && filter.operator !== undefined &&
(filter.value !== undefined || (filter.value !== undefined ||

View File

@ -1 +1,4 @@
export type IAggregateRootRepository = {}; // biome-ignore lint/correctness/noUnusedVariables: <se necesita para definir la interfaz, aunque no se use directamente>
export type IAggregateRootRepository<T> = {
// Define the methods for the aggregate root repository
};