import "reflect-metadata"; import { injectable } from "inversify"; import { NoopTracer, NoopLogger, type ITracer, type ILogger, } from "@repo/core-shared/instrumentation"; import type { IArticlesRepository } from "../../application/repositories/articles.repository.interface"; import type { Article } from "../../entities/models/article"; @injectable() export class MockArticlesRepository implements IArticlesRepository { private _articles: Article[] = []; private tracer: ITracer; private logger: ILogger; constructor( tracer: ITracer = new NoopTracer(), logger: ILogger = new NoopLogger(), ) { this.tracer = tracer; this.logger = logger; void this.logger; // currently unused; reserved for future mock-thrown captures } async getArticle(id: string): Promise
{ return this.tracer.startSpan( { name: "articles.getArticle", op: "repository", attributes: { id } }, async (span) => { const found = this._articles.find((a) => a.id === id); span.setAttribute("found", Boolean(found)); return found; }, ); } async getArticleBySlug(slug: string): Promise
{ return this.tracer.startSpan( { name: "articles.getArticleBySlug", op: "repository", attributes: { slug } }, async (span) => { const found = this._articles.find((a) => a.slug === slug); span.setAttribute("found", Boolean(found)); return found; }, ); } async getArticles(options?: { status?: string; authorId?: string; limit?: number; offset?: number; }): Promise { return this.tracer.startSpan( { name: "articles.getArticles", op: "repository", attributes: { status: options?.status ?? null, authorId: options?.authorId ?? null, limit: options?.limit ?? null, offset: options?.offset ?? null, }, }, async (span) => { let result = [...this._articles]; if (options?.status) { result = result.filter((a) => a.status === options.status); } if (options?.authorId) { result = result.filter((a) => a.authorId === options.authorId); } const offset = options?.offset ?? 0; const limit = options?.limit ?? 50; const sliced = result.slice(offset, offset + limit); span.setAttribute("count", sliced.length); return sliced; }, ); } async createArticle(input: Article): Promise
{ return this.tracer.startSpan( { name: "articles.createArticle", op: "repository", attributes: { slug: input.slug } }, async (span) => { this._articles.push(input); span.setAttribute("id", input.id); return input; }, ); } async updateArticle( id: string, input: Partial
, ): Promise
{ return this.tracer.startSpan( { name: "articles.updateArticle", op: "repository", attributes: { id } }, async (span) => { const idx = this._articles.findIndex((a) => a.id === id); if (idx === -1) { span.setAttribute("found", false); return undefined; } const merged = { ...this._articles[idx]!, ...input, id } as Article; this._articles[idx] = merged; span.setAttribute("found", true); return merged; }, ); } }