forked from Yara724/api
73 lines
2.2 KiB
TypeScript
73 lines
2.2 KiB
TypeScript
import { Injectable, Logger, OnModuleInit } from "@nestjs/common";
|
|
import { InjectModel } from "@nestjs/mongoose";
|
|
import { FilterQuery, Model, UpdateQuery } from "mongoose";
|
|
import { ClientModel, ClientDocument } from "../schema/client.schema";
|
|
|
|
@Injectable()
|
|
export class ClientDbService implements OnModuleInit {
|
|
private readonly logger = new Logger(ClientDbService.name);
|
|
|
|
constructor(
|
|
@InjectModel(ClientModel.name)
|
|
private readonly clientModel: Model<ClientModel>,
|
|
) {}
|
|
|
|
async onModuleInit(): Promise<void> {
|
|
await this.dropLegacyPropertyUniqueIndex();
|
|
}
|
|
|
|
/**
|
|
* `property` was once declared `unique: true` in the schema. Production keeps
|
|
* `autoIndex: false`, so the stale unique index remained and rejected a second
|
|
* client with a missing/null SMS key (E11000 duplicate key).
|
|
*/
|
|
private async dropLegacyPropertyUniqueIndex(): Promise<void> {
|
|
try {
|
|
const indexes = await this.clientModel.collection.indexes();
|
|
for (const index of indexes) {
|
|
if (!index.unique || !index.name || index.name === "_id_") continue;
|
|
|
|
const keys = Object.keys(index.key ?? {});
|
|
const isLegacyPropertyIndex =
|
|
keys.length === 1 &&
|
|
(keys[0] === "property" || keys[0] === "property.smsApiKey");
|
|
|
|
if (!isLegacyPropertyIndex) continue;
|
|
|
|
await this.clientModel.collection.dropIndex(index.name);
|
|
this.logger.warn(
|
|
`Dropped legacy unique index on clients.${keys[0]}: ${index.name}`,
|
|
);
|
|
}
|
|
} catch (err) {
|
|
this.logger.error("Failed to drop legacy client property index", err);
|
|
}
|
|
}
|
|
|
|
async create(client: ClientModel): Promise<ClientModel> {
|
|
return await this.clientModel.create(client);
|
|
}
|
|
|
|
async find(client: FilterQuery<ClientModel>): Promise<ClientDocument> {
|
|
return await this.clientModel.findOne(client);
|
|
}
|
|
|
|
async findOne(client: FilterQuery<ClientModel>) {
|
|
return this.clientModel.findOne(client);
|
|
}
|
|
|
|
async findAll(): Promise<ClientModel[]> {
|
|
return await this.clientModel.find();
|
|
}
|
|
|
|
async findByIdAndUpdate(
|
|
id: string,
|
|
update: UpdateQuery<ClientModel>,
|
|
): Promise<ClientModel | null> {
|
|
return this.clientModel
|
|
.findByIdAndUpdate(id, update, { new: true })
|
|
.lean()
|
|
.exec();
|
|
}
|
|
}
|