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
TypeScript
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;