- 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>
58 lines
1.7 KiB
TypeScript
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,
|
|
});
|
|
}
|
|
}
|