UNPKG

nodedb-json

Version:

A lightweight JSON-based database for Node.js with TypeScript support, indexing, and complex query capabilities

259 lines (258 loc) 13.6 kB
import { Collection } from './collection/collection.js'; import type { AnyValue, PredicateFunction, UpdaterObject, DbOptions, IndexDefinition, QueryOptions, QueryResult, SortOption, PaginationResult, AggregationOption, AggregationResult, CollectionItem, CollectionKey, CloseOptions, DbSchema, MatchObject, SchemaKey, SchemaValue, QueryOptionsWithSelect, QueryResultForOptions } from './types/index.js'; /** * A class to manage JSON-based database operations. */ export declare class NodedbJson<TSchema extends DbSchema = Record<string, any>> { private static readonly BATCH_ALLOWED_METHODS; private filePath; private indexMetaPath; private backupPath; private tempPath; private lockPath; private data; private options; private _pendingChanges; private _indexes; private _indexDefinitions; private storage; private metaStorage; private fileLock; private closed; /** * Creates an instance of NodedbJson. * @param {string} filePath - The path to the JSON file. * @param {DbOptions} [options] - Database options. */ constructor(filePath: string, options?: DbOptions<TSchema>); private readJSONFile; private writeJSONFile; private _createStorage; private _loadIndexDefinitions; private _saveIndexDefinitions; private _getReference; private _assertOpen; /** * Manually save changes to file. * @returns {NodedbJson} - The instance of the database for chaining. */ save(): this; /** * Writes pending changes to disk and returns this instance. */ flush(): this; /** * Reloads data and persisted index definitions from disk. */ reload(): this; /** * Flushes pending changes and releases the process-level file lock. */ close(options?: CloseOptions): void; /** * Sets a value in the JSON data. * @param {string} key - The key to set. * @param {any} value - The value to set. * @returns {NodedbJson} - The instance of the database for chaining. */ set<K extends SchemaKey<TSchema>>(key: K, value: TSchema[K]): this; set(key: string, value: AnyValue): this; /** * Gets a value from the JSON data. * @param {string} key - The key to get. * @returns {any} - The value. */ get<K extends SchemaKey<TSchema>>(key: K): SchemaValue<TSchema[K]>; get(key: string): AnyValue; /** * Gets the internal mutable reference for advanced use cases. * Mutating this value bypasses change tracking, auto-save, and index updates. * Prefer set, push, update, delete, or mutate for normal writes. * @param {string} key - The key to get. * @returns {any} - The internal value reference. */ getUnsafeReference<K extends SchemaKey<TSchema>>(key: K): SchemaValue<TSchema[K]>; getUnsafeReference(key: string): AnyValue; /** * Mutates a value through a controlled callback and refreshes indexes. * @param {string} key - The key to mutate. * @param {function} mutator - Callback that receives the internal value. * @returns {NodedbJson} - The instance of the database for chaining. */ mutate<K extends SchemaKey<TSchema>>(key: K, mutator: (value: TSchema[K]) => void): this; mutate<T = any>(key: string, mutator: (value: T) => void): this; /** * Checks if a key exists in the JSON data. * @param {string} key - The key to check. * @returns {boolean} - True if the key exists, otherwise false. */ has(key: string): boolean; /** * Updates a value in the JSON data. * @param {string} key - The key to update. * @param {function|object} predicateOrUpdater - The predicate function or updater object. * @param {object} [updater] - The updater object if a predicate function is provided. * @returns {NodedbJson} - The instance of the database for chaining. */ update<K extends CollectionKey<TSchema>>(key: K, predicateOrUpdater: PredicateFunction<CollectionItem<TSchema, K>> | MatchObject<CollectionItem<TSchema, K>>, updater: UpdaterObject<CollectionItem<TSchema, K>>): this; update<K extends SchemaKey<TSchema>>(key: K, updater: UpdaterObject<TSchema[K]>): this; update<T>(key: string, predicateOrUpdater: PredicateFunction<T> | UpdaterObject<T>, updater?: UpdaterObject<T>): this; /** * Deletes a value from the JSON data. * @param {string} key - The key to delete. * @param {function|any[]} [predicateOrKeys] - The predicate function or array of keys to delete. * @param {string} [field='id'] - The field to match for array deletion. * @returns {NodedbJson} - The instance of the database for chaining. */ delete<K extends CollectionKey<TSchema>>(key: K, predicateOrKeys: PredicateFunction<CollectionItem<TSchema, K>> | Array<CollectionItem<TSchema, K>[keyof CollectionItem<TSchema, K>]>, field?: Extract<keyof CollectionItem<TSchema, K>, string>): this; delete<K extends SchemaKey<TSchema>>(key: K, objectKeys?: Array<Extract<keyof TSchema[K], string>>): this; delete<T>(key: string, predicateOrKeys?: PredicateFunction<T> | any[], field?: string): this; /** * Finds a value in the JSON data. * @param {string} key - The key to find. * @param {function} predicate - The predicate function to match. * @returns {any} - The found value. */ find<K extends CollectionKey<TSchema>>(key: K, predicate: PredicateFunction<CollectionItem<TSchema, K>>): CollectionItem<TSchema, K> | undefined; find<T>(key: string, predicate: PredicateFunction<T>): T | undefined; /** * Finds a value by field and value using index if available. * @param {string} key - The key to find. * @param {string} field - The field to match. * @param {any} value - The value to match. * @returns {any} - The found value. */ findByField<K extends CollectionKey<TSchema>>(key: K, field: Extract<keyof CollectionItem<TSchema, K>, string>, value: CollectionItem<TSchema, K>[keyof CollectionItem<TSchema, K>]): CollectionItem<TSchema, K> | undefined; findByField<T>(key: string, field: string, value: any): T | undefined; /** * Filters values in the JSON data. * @param {string} key - The key to filter. * @param {function} predicate - The predicate function to match. * @returns {any[]} - The filtered values. */ filter<K extends CollectionKey<TSchema>>(key: K, predicate: PredicateFunction<CollectionItem<TSchema, K>>): CollectionItem<TSchema, K>[]; filter<T>(key: string, predicate: PredicateFunction<T>): T[]; /** * Filters values by field and possible values using index if available. * @param {string} key - The key to filter. * @param {string} field - The field to match. * @param {any[]} values - The values to match. * @returns {any[]} - The filtered values. */ filterByField<K extends CollectionKey<TSchema>>(key: K, field: Extract<keyof CollectionItem<TSchema, K>, string>, values: Array<CollectionItem<TSchema, K>[keyof CollectionItem<TSchema, K>]>): CollectionItem<TSchema, K>[]; filterByField<T>(key: string, field: string, values: any[]): T[]; /** * Pushes a value into an array in the JSON data. * @param {string} key - The key to push to. * @param {any|any[]} value - The value or values to push. * @returns {NodedbJson} - The instance of the database for chaining. */ push<K extends CollectionKey<TSchema>>(key: K, value: CollectionItem<TSchema, K> | CollectionItem<TSchema, K>[]): this; push(key: string, value: AnyValue | AnyValue[]): this; /** * Executes multiple operations in batch. * @param {Array<{method: string, args: any[]}>} operations - Array of operations to execute. * @returns {NodedbJson} - The instance of the database for chaining. */ batch(operations: Array<{ method: string; args: any[]; }>): this; /** * 创建一个索引 * @param {string} key - 要索引的集合路径 * @param {IndexDefinition} indexDefinition - 索引定义 * @returns {NodedbJson} - 实例,支持链式调用 */ createIndex<K extends CollectionKey<TSchema>>(key: K, indexDefinition: IndexDefinition<CollectionItem<TSchema, K>>): this; createIndex(key: string, indexDefinition: IndexDefinition<any>): this; /** * 删除索引 * @param {string} key - 集合路径 * @param {string} field - 字段名 * @returns {NodedbJson} - 实例,支持链式调用 */ dropIndex<K extends CollectionKey<TSchema>>(key: K, field: Extract<keyof CollectionItem<TSchema, K>, string>): this; dropIndex(key: string, field: string): this; /** * 获取所有索引信息 * @returns {Record<string, Record<string, IndexDefinition>>} - 索引定义 */ getIndexes(): Record<string, Record<string, IndexDefinition>>; private _hasIndexDefinition; private _hasIndexOnField; private _hasBuiltIndexOnField; private _rebuildAllIndexes; private _rebuildIndexesForKey; private _assertUniqueIndexesForKey; private _assertUniqueIndexForDefinition; private _buildIndex; private _findIndexedItemPosition; private _getItemIndexByField; private _getItemIndexesByField; private _getIndexValueMode; /** * 复杂查询操作,支持排序、分页、聚合等 * @param {string} key - 集合路径 * @param {QueryOptions} options - 查询选项 * @returns {QueryResult} - 查询结果 */ query<K extends CollectionKey<TSchema>, TSelected extends Extract<keyof CollectionItem<TSchema, K>, string>>(key: K, options: QueryOptionsWithSelect<CollectionItem<TSchema, K>, TSelected>): QueryResult<Pick<CollectionItem<TSchema, K>, TSelected>>; query<K extends CollectionKey<TSchema>, TOptions extends QueryOptions<CollectionItem<TSchema, K>>>(key: K, options: TOptions): QueryResultForOptions<CollectionItem<TSchema, K>, TOptions>; query<K extends CollectionKey<TSchema>>(key: K, options?: QueryOptions<CollectionItem<TSchema, K>>): QueryResult<CollectionItem<TSchema, K>>; query<T = any, TSelected extends Extract<keyof T, string> = Extract<keyof T, string>>(key: string, options: QueryOptionsWithSelect<T, TSelected>): QueryResult<Pick<T, TSelected>>; query<T = any, TOptions extends QueryOptions<T> = QueryOptions<T>>(key: string, options: TOptions): QueryResultForOptions<T, TOptions>; query<T = any>(key: string, options?: QueryOptions<T>): QueryResult<T>; private _applySort; /** * 快速排序查询(优化版本) * @param {string} key - 集合路径 * @param {SortOption | SortOption[]} sort - 排序选项 * @param {number} [limit] - 限制返回数量 * @returns {T[]} - 排序后的数据 */ orderBy<K extends CollectionKey<TSchema>>(key: K, sort: SortOption<CollectionItem<TSchema, K>> | SortOption<CollectionItem<TSchema, K>>[], limit?: number): CollectionItem<TSchema, K>[]; orderBy<T = any>(key: string, sort: SortOption<T> | SortOption<T>[], limit?: number): T[]; /** * 快速分页查询 * @param {string} key - 集合路径 * @param {number} page - 页码(从1开始) * @param {number} pageSize - 每页数量 * @param {PredicateFunction<T> | Record<string, any>} [where] - 过滤条件 * @returns {PaginationResult<T>} - 分页结果 */ paginate<K extends CollectionKey<TSchema>>(key: K, page: number, pageSize: number, where?: PredicateFunction<CollectionItem<TSchema, K>> | MatchObject<CollectionItem<TSchema, K>>): PaginationResult<CollectionItem<TSchema, K>>; paginate<T = any>(key: string, page: number, pageSize: number, where?: PredicateFunction<T> | MatchObject<T>): PaginationResult<T>; /** * 聚合查询 * @param {string} key - 集合路径 * @param {AggregationOption[]} aggregations - 聚合选项 * @param {PredicateFunction<T> | Record<string, any>} [where] - 过滤条件 * @returns {AggregationResult[]} - 聚合结果 */ aggregate<K extends CollectionKey<TSchema>>(key: K, aggregations: AggregationOption[], where?: PredicateFunction<CollectionItem<TSchema, K>> | MatchObject<CollectionItem<TSchema, K>>): AggregationResult[]; aggregate<T = any>(key: string, aggregations: AggregationOption[], where?: PredicateFunction<T> | MatchObject<T>): AggregationResult[]; /** * 统计查询 * @param {string} key - 集合路径 * @param {PredicateFunction<T> | Record<string, any>} [where] - 过滤条件 * @returns {number} - 统计数量 */ count<K extends CollectionKey<TSchema>>(key: K, where?: PredicateFunction<CollectionItem<TSchema, K>> | MatchObject<CollectionItem<TSchema, K>>): number; count<T = any>(key: string, where?: PredicateFunction<T> | MatchObject<T>): number; /** * 去重查询 * @param {string} key - 集合路径 * @param {string} field - 去重字段 * @returns {any[]} - 去重后的值数组 */ distinct<K extends CollectionKey<TSchema>>(key: K, field: Extract<keyof CollectionItem<TSchema, K>, string>): Array<CollectionItem<TSchema, K>[keyof CollectionItem<TSchema, K>]>; distinct(key: string, field: string): any[]; /** * Creates a typed collection helper for an array path. * This is a lightweight wrapper over the existing root methods. */ collection<K extends CollectionKey<TSchema>>(key: K): Collection<CollectionItem<TSchema, K>>; collection<T = any>(key: string): Collection<T>; } export default NodedbJson;