@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
TypeScript
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 {};