UNPKG

@push.rocks/smartdata

Version:

An advanced library for NoSQL data organization and manipulation using TypeScript with support for MongoDB, data validation, collections, and custom data types.

312 lines (311 loc) 11.6 kB
import * as plugins from './plugins.js'; import { SmartdataDbCursor } from './classes.cursor.js'; import { type IManager, SmartdataCollection } from './classes.collection.js'; import { SmartdataDbWatcher } from './classes.watcher.js'; /** * Search options for `.search()`: * - filter: additional MongoDB query to AND-merge * - validate: post-fetch validator, return true to keep a doc */ export interface SearchOptions<T> { /** * Additional MongoDB filter to AND‐merge into the query */ filter?: Record<string, any>; /** * Post‐fetch validator; return true to keep each doc */ validate?: (doc: T) => Promise<boolean> | boolean; /** * Optional MongoDB session for transactional operations */ session?: plugins.mongodb.ClientSession; } export type TDocCreation = 'db' | 'new' | 'mixed'; export declare function globalSvDb(): (value: undefined, context: ClassFieldDecoratorContext) => void; /** * Options for custom serialization/deserialization of a field. */ export interface SvDbOptions { /** Function to serialize the field value before saving to DB */ serialize?: (value: any) => any; /** Function to deserialize the field value after reading from DB */ deserialize?: (value: any) => any; } /** * saveable - saveable decorator to be used on class properties */ export declare function svDb(options?: SvDbOptions): (value: undefined, context: ClassFieldDecoratorContext) => void; /** * searchable - marks a property as searchable with Lucene query syntax */ export declare function searchable(): (value: undefined, context: ClassFieldDecoratorContext) => void; /** * unique index - decorator to mark a unique index */ export declare function unI(): (value: undefined, context: ClassFieldDecoratorContext) => void; /** * Options for MongoDB indexes */ export interface IIndexOptions { background?: boolean; unique?: boolean; sparse?: boolean; expireAfterSeconds?: number; [key: string]: any; } /** * index - decorator to mark a field for regular indexing */ export declare function index(options?: IIndexOptions): (value: undefined, context: ClassFieldDecoratorContext) => void; type ElementOf<T> = T extends ReadonlyArray<infer U> ? U : T; type InValues<T> = ReadonlyArray<ElementOf<T>>; export type MongoFilterCondition<T> = T | { $eq?: T; $ne?: T; $gt?: T; $gte?: T; $lt?: T; $lte?: T; $in?: InValues<T>; $nin?: InValues<T>; $exists?: boolean; $type?: string | number; $regex?: string | RegExp; $options?: string; $all?: T extends ReadonlyArray<infer U> ? ReadonlyArray<U> : never; $elemMatch?: T extends ReadonlyArray<infer U> ? MongoFilter<U> : never; $size?: T extends ReadonlyArray<any> ? number : never; $not?: MongoFilterCondition<T>; }; export type MongoFilter<T> = { [K in keyof T]?: T[K] extends object ? T[K] extends any[] ? MongoFilterCondition<T[K]> : MongoFilter<T[K]> | MongoFilterCondition<T[K]> : MongoFilterCondition<T[K]>; } & { $and?: MongoFilter<T>[]; $or?: MongoFilter<T>[]; $nor?: MongoFilter<T>[]; $not?: MongoFilter<T>; [key: string]: any; }; export declare const convertFilterForMongoDb: (filterArg: { [key: string]: any; }) => { [key: string]: any; }; export declare class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends IManager = any> { /** * the collection object an Doc belongs to */ static collection: SmartdataCollection<any>; collection: SmartdataCollection<any>; static defaultManager: any; static manager: any; manager: TManager; /** * Helper to get collection with fallback to static for Deno compatibility */ private getCollectionSafe; static createInstanceFromMongoDbNativeDoc<T>(this: plugins.tsclass.typeFest.Class<T>, mongoDbNativeDocArg: any): T; /** * gets all instances as array * @param this * @param filterArg - Type-safe MongoDB filter with nested object support and operators * @returns */ static getInstances<T>(this: plugins.tsclass.typeFest.Class<T>, filterArg: MongoFilter<T>, opts?: { session?: plugins.mongodb.ClientSession; }): Promise<T[]>; /** * Cursor-paged query with stable seek pagination — the org-standard way to * list unbounded collections. Orders by a comparable (ideally indexed) * sort field with a unique tiebreaker, returns one page plus the cursor * for the next, and never materializes the full result set. */ static getPagedInstances<T>(this: plugins.tsclass.typeFest.Class<T>, optionsArg: { filter?: MongoFilter<T>; /** Comparable, ideally indexed field that orders the pages (e.g. a numeric timestamp). */ sortField: string; sortDirection?: 'asc' | 'desc'; /** Unique tiebreaker field present on every document. Defaults to 'id'. */ uniqueField?: string; /** Page size, default 100, capped at 1000. */ limit?: number; /** Seek position returned as nextCursor by the previous page. */ cursor?: { sortValue: number | string; uniqueValue: string; }; /** Also count all filter matches (extra query). */ withTotal?: boolean; session?: plugins.mongodb.ClientSession; }): Promise<{ documents: T[]; nextCursor?: { sortValue: number | string; uniqueValue: string; }; total?: number; }>; /** * gets the first matching instance * @param this * @param filterArg * @returns */ static getInstance<T>(this: plugins.tsclass.typeFest.Class<T>, filterArg: MongoFilter<T>, opts?: { session?: plugins.mongodb.ClientSession; }): Promise<T>; /** * get a unique id prefixed with the class name */ static getNewId<T = any>(this: plugins.tsclass.typeFest.Class<T>, lengthArg?: number): Promise<string>; /** * Get a cursor for streaming results, with optional session and native cursor modifiers. * @param filterArg Partial filter to apply * @param opts Optional session and modifier for the raw MongoDB cursor */ static getCursor<T>(this: plugins.tsclass.typeFest.Class<T>, filterArg: MongoFilter<T>, opts?: { session?: plugins.mongodb.ClientSession; modifier?: (cursorArg: plugins.mongodb.FindCursor<plugins.mongodb.WithId<plugins.mongodb.BSON.Document>>) => plugins.mongodb.FindCursor<plugins.mongodb.WithId<plugins.mongodb.BSON.Document>>; }): Promise<SmartdataDbCursor<T>>; /** * watch the collection * @param this * @param filterArg * @param forEachFunction */ /** * Watch the collection for changes, with optional buffering and change stream options. * @param filterArg MongoDB filter to select which changes to observe * @param opts optional ChangeStreamOptions plus bufferTimeMs */ static watch<T>(this: plugins.tsclass.typeFest.Class<T>, filterArg: MongoFilter<T>, opts?: plugins.mongodb.ChangeStreamOptions & { bufferTimeMs?: number; }): Promise<SmartdataDbWatcher<T>>; /** * run a function for all instances * @returns */ static forEach<T>(this: plugins.tsclass.typeFest.Class<T>, filterArg: MongoFilter<T>, forEachFunction: (itemArg: T) => Promise<any>): Promise<void>; /** * returns a count of the documents in the collection */ static getCount<T>(this: plugins.tsclass.typeFest.Class<T>, filterArg?: MongoFilter<T>): Promise<number>; /** * Runs an integrity check on this collection. * Returns a summary with estimated vs actual counts and any duplicate unique fields. */ static checkCollectionIntegrity<T>(this: plugins.tsclass.typeFest.Class<T>): Promise<{ ok: boolean; estimatedCount: number; actualCount: number; duplicateFields: Array<{ field: string; duplicateValues: number; }>; }>; /** * Create a MongoDB filter from a Lucene query string * @param luceneQuery Lucene query string * @returns MongoDB query object */ static createSearchFilter<T>(this: plugins.tsclass.typeFest.Class<T>, luceneQuery: string): any; /** * List all searchable fields defined on this class */ static getSearchableFields(): string[]; /** * Execute a query with optional hard filter and post-fetch validation */ private static execQuery; /** * Search documents by text or field:value syntax, with safe regex fallback * Supports additional filtering and post-fetch validation via opts * @param query A search term or field:value expression * @param opts Optional filter and validate hooks * @returns Array of matching documents */ static search<T>(this: plugins.tsclass.typeFest.Class<T>, query: string, opts?: SearchOptions<T>): Promise<T[]>; /** * how the Doc in memory was created, may prove useful later. */ creationStatus: TDocCreation; /** * updated from db in any case where doc comes from db */ _createdAt: string; /** * will be updated everytime the doc is saved */ _updatedAt: string; /** * an array of saveable properties of ALL doc * Note: Set by decorators on prototype - NOT declared as instance property to avoid shadowing in Deno * Declared with definite assignment assertion to satisfy TypeScript without creating instance property */ globalSaveableProperties: string[]; /** * unique indexes * Note: Set by decorators on prototype - NOT declared as instance property to avoid shadowing in Deno */ uniqueIndexes: string[]; /** * regular indexes with their options * Note: Set by decorators on prototype - NOT declared as instance property to avoid shadowing in Deno */ regularIndexes: Array<{ field: string; options: IIndexOptions; }>; /** * an array of saveable properties of a specific doc * Note: Set by decorators on prototype - NOT declared as instance property to avoid shadowing in Deno */ saveableProperties: string[]; /** * name */ name: string; /** * primary id in the database */ dbDocUniqueId: string; /** * class constructor */ constructor(); /** * saves this instance (optionally within a transaction) */ save(opts?: { session?: plugins.mongodb.ClientSession; }): Promise<any>; /** * deletes a document from the database (optionally within a transaction) */ delete(opts?: { session?: plugins.mongodb.ClientSession; }): Promise<any>; /** * also store any referenced objects to DB * better for data consistency */ saveDeep(savedMapArg?: plugins.lik.ObjectMap<SmartDataDbDoc<any, any>>): void; /** * updates an object from db */ updateFromDb(): Promise<boolean>; /** * creates a saveable object so the instance can be persisted as json in the database * * Properties whose value is `undefined` are omitted entirely rather than * written as BSON null, so "absent" stays representable. Explicit `null` is * untouched and remains storable wherever the field type allows it. */ createSavableObject(): Promise<TImplements>; /** * creates an identifiable object for operations that require filtering */ createIdentifiableObject(): Promise<any>; } export {};