UNPKG

afridho-mongodb

Version:

A simple MongoDB client wrapper for easy database operations

377 lines (376 loc) 13.5 kB
import { MongoClient, Document, ObjectId } from "mongodb"; declare global { var _mongoClient: MongoClient | undefined; } interface ReadAllOptions { /** * Optional sort object, e.g. { createdAt: 1 } for ascending or { createdAt: -1 } for descending */ sort?: Document; limit?: number; skip?: number; } /** * Class representing a MongoDB client for a specific collection. */ declare class ClientDB { /** * Returns the native MongoDB Db instance from the global connection. * Useful for libraries that require a direct Db object (e.g. Better-Auth). */ static getNativeDb(): Promise<import("mongodb").Db>; /** * Returns the native MongoDB Db instance for this instance's connection. */ getNativeDb(): Promise<import("mongodb").Db>; /** * Returns the native MongoDB Db instance synchronously. * The driver will handle connection queuing in the background. */ static getNativeDbSync(): import("mongodb").Db; private client; private collectionName; private collection; /** * Creates an instance of ClientDB. * @param {string} collectionName - The name of the collection to interact with. */ constructor(collectionName: string); /** * Connects to the MongoDB database and initializes the collection. * @returns {Promise<void>} */ connect(): Promise<void>; /** * Helper to convert _id string to ObjectId if needed * @param {Document} query - The query object to preprocess * @returns {Document} The processed query with _id converted if applicable */ private preprocessQuery; /** * Reads a document from the collection based on the provided query. * @param {Document} query - The query to find the document. * @returns {Promise<Document|null>} The found document or null if not found. */ read(query: Document): Promise<Document | null>; /** * Reads all documents from the collection with optional sorting. * @param {ReadAllOptions} [options] - Optional options object. * @param {Document} [options.sort] - Optional sort object, e.g. { createdAt: 1 } for ascending. * @returns {Promise<Document[]>} An array of all documents, optionally sorted. */ readAll(options?: ReadAllOptions): Promise<Document[]>; /** * Inserts a new document into the collection. * @param {Document} data - The data to insert. * @returns {Promise<Document>} The result of the insert operation. */ insert(data: Document): Promise<Document>; /** * Inserts multiple documents into the collection. * @param {Document[]} data - The data to insert. * @returns {Promise<Document>} The result of the insert operation. */ insertMany(data: Document[]): Promise<Document>; /** * Updates a document in the collection based on the provided query. * @param {Document} query - The query to find the document to update. * @param {Document} data - The data to update. * @returns {Promise<Document>} The result of the update operation. */ update(query: Document, data: Document): Promise<Document>; /** * Updates multiple documents in the collection. * - If you pass Mongo operators ($set, $inc, etc), it will use them directly. * - If you pass a plain object, it will wrap it inside $set. * * @param {Document} query - The filter to match documents. * @param {Document} data - The update data (plain object or with operators). * @returns {Promise<Document>} The result of the update operation. */ updateMany(query: Document, data: Document | Document[], options?: { upsert?: boolean; }): Promise<Document>; /** * Deletes a document from the collection based on the provided query. * @param {Document} query - The query to find the document to delete. * @returns {Promise<Document>} The result of the delete operation. */ delete(query: Document): Promise<Document>; /** * Deletes multiple documents from the collection based on the provided query. * @param {Document} query - The query to find the documents to delete. * @returns {Promise<Document>} The result of the delete operation. */ deleteMany(query: Document): Promise<Document>; /** * Finds multiple documents in the collection based on the provided query. * @param {Document} query - The query to find the documents. * @returns {Promise<Document[]>} An array of found documents. */ find(query: Document, options?: ReadAllOptions, project?: Document): Promise<Document[]>; /** * Reads multiple documents from the collection based on a query. * @param {Document} query - The filter query. * @returns {Promise<Document[]>} Array of matching documents. */ readMany(query: Document): Promise<Document[]>; /** * Gets random documents from the collection. * @param {number} [total=1] - The number of random documents to retrieve. * @returns {Promise<Document[]>} An array of random documents. */ getRandomData(total?: number): Promise<Document[]>; /** * Run an aggregation pipeline on the current collection. * * @param {Array<Document>} pipeline - An array of MongoDB aggregation stages. * Example: * [ * { $unwind: "$tags" }, * { $group: { _id: "$tags", count: { $sum: 1 } } }, * { $sort: { count: -1 } }, * { $limit: 10 } * ] * * @returns {Promise<Document[]>} Resolves with the array of aggregation results. * * @throws {Error} If the aggregation query fails. */ aggregate(pipeline?: Document[]): Promise<Document[]>; /** * Gets the storage statistics for the collection. * @returns {Promise<{storageSize: number, size: number, count: number}>} The storage statistics including storageSize. */ getStorageStats(): Promise<{ storageSize: number; size: number; count: number; }>; /** * Gets cluster-wide storage statistics. */ static getClusterStats(): Promise<{ totalDataSize: number; totalStorageSize: number; totalIndexSize: number; databases: any[]; }>; /** * Closes the MongoDB connection. * @returns {Promise<void>} */ close(): Promise<void>; /** * Finds documents in the current collection and dynamically joins related collections * using MongoDB's `$lookup` aggregation stage. * * This is useful when you want to "populate" data from other collections * (similar to Mongoose's populate) but in a flexible, dynamic way. * * ### Example: * ```ts * const tasks = await tasksDb.findWithRelations( * { column: "todo" }, // filter * [ * { * from: "kanban_tags", * localField: "tags", * foreignField: "value", * as: "tags" * }, * { * from: "kanban_persons", * localField: "persons", * foreignField: "_id", * as: "persons", * isObjectId: true // convert string IDs to ObjectId * } * ], * { * title: 1, * description: 1, * "tags.label": 1, * "persons.name": 1 * }, * { * sort: { createdAt: -1 }, * limit: 10, * skip: 20 * } * ); * ``` * * @param {Document} [filter={}] - MongoDB query filter. Defaults to `{}` (fetch all). * @param {Object[]} [relations=[]] - Array of relation configurations for `$lookup`. * @param {string} relations[].from - Target collection name to join with. * @param {string} relations[].localField - Field in this collection that holds the reference. * @param {string} relations[].foreignField - Field in the target collection to match against. * @param {string} relations[].as - The alias name for the joined data in the output. * @param {boolean} [relations[].isObjectId] - If `true`, will map string IDs in `localField` into ObjectId before lookup. * @param {Document} [project={}] - Optional MongoDB projection object to limit fields in the final output. * @param {ReadAllOptions} [options={}] - Optional settings like sort, skip, and limit. * * @returns {Promise<Document[]>} A promise that resolves to an array of documents with joined relations applied. */ findWithRelations(filter?: Document, relations?: { from: string; localField: string; foreignField: string; as: string; isObjectId?: boolean; isSingle?: boolean; }[], project?: Document, options?: ReadAllOptions): Promise<Document[]>; /** * Finds a single document in the current collection and dynamically joins related collections * using MongoDB's `$lookup` aggregation stage. * * Mirip dengan `findWithRelations`, tapi hanya return satu dokumen (bukan array). * * ### Example: * ```ts * const task = await tasksDb.findOneWithRelations( * { _id: "66cfa89f3c9c7d776b5f4f10" }, * [ * { * from: "kanban_tags", * localField: "tags", * foreignField: "value", * as: "tags" * }, * { * from: "kanban_persons", * localField: "persons", * foreignField: "_id", * as: "persons", * isObjectId: true * } * ] * ); * ``` * * @param {Document} filter - MongoDB query filter. Biasanya pakai `_id`. * @param {Object[]} [relations=[]] - Array of relation configs sama seperti `findWithRelations`. * @param {Document} [project={}] - Projection untuk limit field output. * * @returns {Promise<Document | null>} A single document with joined relations, or `null`. */ findOneWithRelations(filter: Document, relations?: { from: string; localField: string; foreignField: string; as: string; isObjectId?: boolean; isSingle?: boolean; }[], project?: Document): Promise<Document | null>; /** * Counts the number of documents matching the query. * Alias for countDocuments. * @param {Document} [query={}] - Optional filter query. * @returns {Promise<number>} The count of matching documents. */ count(query?: Document): Promise<number>; /** * Counts the number of documents matching the query. * @param {Document} [query={}] - Optional filter query. * @returns {Promise<number>} The count of matching documents. */ countDocuments(query?: Document): Promise<number>; /** * One-time migration: convert string date fields to Date objects. * * @param fields - Which fields to convert (default: createdAt, updatedAt, startAt, endAt) * @returns number of documents updated */ migrateDateFields(fields?: string[]): Promise<number>; /** * INTERNAL: Connect to external cluster */ private static _connectExternal; /** * INCREMENTAL BACKUP (NO DELETE): * - Hanya ambil dokumen yang updatedAt > lastBackupAt * - Tidak pernah hapus dokumen di backup * - Upsert-only */ static incrementalBackupOneDatabase(params: { targetUri: string; sourceDb: string; targetDb: string; }): Promise<{ mode: string; sourceDb: string; targetDb: string; lastBackupAt: Date; executedAt: Date; report: any[]; }>; /** * MULTI-DATABASE INCREMENTAL (NO DELETE) */ static incrementalBackupManyDatabases(targetUri: string, dbList: string[]): Promise<{ mode: string; targetUri: string; results: any[]; }>; /** * DELTA BACKUP (NO DELETE): * - hanya dokumen baru (yang belum ada _id nya di backup) * - tidak pernah hapus */ static deltaBackupOneDatabase(params: { targetUri: string; sourceDb: string; targetDb: string; }): Promise<{ mode: string; sourceDb: string; targetDb: string; report: any[]; }>; /** * MULTI-DATABASE DELTA (NO DELETE) */ static deltaBackupManyDatabases(targetUri: string, dbList: string[]): Promise<{ mode: string; targetUri: string; results: any[]; }>; static fullSyncOneDatabase(params: { sourceUri: string; targetUri: string; dbName: string; }): Promise<{ mode: string; sourceDb: string; snapshotDb: string; inserted: number; updated: number; deleted: number; report: any[]; }>; static fullSyncManyDatabases(params: { targetURI: string; dbs: string[]; keepWeeks?: number; }): Promise<{ mode: string; syncedDatabases: string[]; results: PromiseSettledResult<{ mode: string; sourceDb: string; snapshotDb: string; inserted: number; updated: number; deleted: number; report: any[]; }>[]; }>; static cleanupSnapshots(params: { targetURI: string; dbs: string[]; keepWeeks?: number; }): Promise<void>; } export default ClientDB; export { ObjectId };