Files
task-stream/libs/api/identity/infrastructure/src/lib/mongo/mongo-user.registry.ts
Josep Piguillem 2c501a50d0 feat: uuid ids everywhere, pickers for linked tickets, @pi/ui checkboxes
- Postgres: every table has a uuid `id` (gen_random_uuid()); the event
  store keeps its relay order in `seq`, and the lookup tables their
  uniqueness in constraints of their own.
- MongoDB: `_id` is Mongo's ObjectId; `id` is the domain id (the same
  uuid as the aggregate's stream in Postgres), unique, and every query
  goes by it. Production starts from empty databases.
- Web: linking tickets and hanging one from a parent are picked from a
  searchable select (links across projects, parents within the project)
  instead of typing a key; every checkbox is @pi/ui's pi-checkbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:16:43 +02:00

58 lines
1.7 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { UserRegistry } from '@task-stream/api/identity/application';
import { User, UserFactory } from '@task-stream/api/identity/domain';
import { Model } from 'mongoose';
import { UserDocument } from './user.schema';
@Injectable()
export class MongoUserRegistry extends UserRegistry {
constructor(
@InjectModel(UserDocument.name) private readonly users: Model<UserDocument>,
private readonly factory: UserFactory,
) {
super();
}
async upsert(user: User): Promise<void> {
await this.users.updateOne(
{ id: user.id },
{ $set: { name: user.name, email: user.email, isActive: user.isActive } },
{ upsert: true },
);
}
async findById(id: string): Promise<User | null> {
const doc = await this.users.findOne({ id }).lean();
return doc ? this.toUser(doc) : null;
}
async findByIds(ids: string[]): Promise<User[]> {
if (ids.length === 0) return [];
const docs = await this.users.find({ id: { $in: ids } }).lean();
return docs.map((d) => this.toUser(d));
}
async search(term: string, limit: number): Promise<User[]> {
const pattern = new RegExp(
term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),
'i',
);
const docs = await this.users
.find(term ? { $or: [{ name: pattern }, { email: pattern }] } : {})
.sort({ name: 1 })
.limit(limit)
.lean();
return docs.map((d) => this.toUser(d));
}
private toUser(doc: UserDocument): User {
return this.factory.restore({
id: doc.id,
name: doc.name,
email: doc.email,
isActive: doc.isActive,
});
}
}