tbdb 0.0.0 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +72 -0
  2. package/dist/adapter/IndexedDB/IndexedDBAdapter.d.ts +29 -0
  3. package/dist/adapter/IndexedDB/index.d.ts +1 -0
  4. package/dist/adapter/IndexedDB/test/indexeddb.test.d.ts +1 -0
  5. package/dist/adapter/SQLite/SQLiteAdapter.d.ts +137 -15
  6. package/dist/adapter/SQLite/benchmark/query_analysis.bench.d.ts +1 -0
  7. package/dist/adapter/SQLite/benchmark/sqlite-extended.bench.d.ts +9 -0
  8. package/dist/adapter/SQLite/benchmark/sqlite.bench.d.ts +1 -0
  9. package/dist/adapter/SQLite/driver/BetterSqlite3Driver.d.ts +27 -0
  10. package/dist/adapter/SQLite/driver/BunSqliteDriver.d.ts +68 -0
  11. package/dist/adapter/SQLite/driver/NodeSqliteDriver.d.ts +60 -0
  12. package/dist/adapter/SQLite/driver/index.d.ts +51 -0
  13. package/dist/adapter/SQLite/driver/test/driver.test.d.ts +6 -0
  14. package/dist/adapter/SQLite/driver/types.d.ts +106 -0
  15. package/dist/adapter/SQLite/index.d.ts +3 -0
  16. package/dist/adapter/SQLite/test/dirty-tracking-bugs.test.d.ts +24 -0
  17. package/dist/adapter/SQLite/test/dirty-tracking-production.test.d.ts +11 -0
  18. package/dist/adapter/SQLite/test/side-table-bug-verify.test.d.ts +14 -0
  19. package/dist/adapter/SQLite/test/side-table-bugs.test.d.ts +17 -0
  20. package/dist/adapter/SQLite/test/side-table-edge-cases.test.d.ts +15 -0
  21. package/dist/adapter/SQLite/test/sqlite-datatypes.test.d.ts +5 -0
  22. package/dist/adapter/SQLite/test/sqlite-multi-driver.test.d.ts +6 -0
  23. package/dist/adapter/SQLite/test/sqlite-query-ops.test.d.ts +4 -0
  24. package/dist/adapter/SQLite/utils/mongoToSql.d.ts +4 -1
  25. package/dist/adapter/SQLite/utils/projection.d.ts +16 -0
  26. package/dist/adapter/SQLite/utils/queryAnalysis.d.ts +54 -0
  27. package/dist/adapter/SQLite/utils/serializer.d.ts +19 -2
  28. package/dist/adapter/SQLite/utils/zstdHelper.d.ts +2 -2
  29. package/dist/adapter/adapter.d.ts +62 -3
  30. package/dist/benchmark/dist/base.try.d.ts +1 -0
  31. package/dist/core/Table.d.ts +15 -9
  32. package/dist/core/defineTable.d.ts +10 -4
  33. package/dist/core/event.d.ts +24 -0
  34. package/dist/core/types.d.ts +1 -1
  35. package/dist/extension/tree/TableTree.d.ts +49 -0
  36. package/dist/extension/tree/core/copyNodes.d.ts +36 -0
  37. package/dist/extension/tree/core/createNodes.d.ts +33 -0
  38. package/dist/extension/tree/core/deleteNodes.d.ts +33 -0
  39. package/dist/extension/tree/core/listNodes.d.ts +32 -0
  40. package/dist/extension/tree/core/listNodesByCursor.d.ts +31 -0
  41. package/dist/extension/tree/core/moveNodes.d.ts +25 -0
  42. package/dist/extension/tree/core/preOverwriteNodes.d.ts +41 -0
  43. package/dist/extension/tree/core/presyncNodes.d.ts +30 -0
  44. package/dist/extension/tree/core/setNodes.d.ts +49 -0
  45. package/dist/extension/tree/core/unDeleteNodes.d.ts +28 -0
  46. package/dist/extension/tree/core/updateNodes.d.ts +29 -0
  47. package/dist/extension/tree/demo/dist-web/assets/index-DT1zZc4B.d.ts +1 -0
  48. package/dist/extension/tree/demo/src/main.d.ts +1 -0
  49. package/dist/extension/tree/demo/src/server.d.ts +1 -0
  50. package/dist/extension/tree/demo/vite.config.d.ts +2 -0
  51. package/dist/extension/tree/index.d.ts +1 -0
  52. package/dist/extension/tree/test/benchmark/ManyMany.bench.d.ts +1 -0
  53. package/dist/extension/tree/test/benchmark/table-tree.bench.d.ts +1 -0
  54. package/dist/extension/tree/test/gemini/table-tree-gemini-TableTree.test.d.ts +1 -0
  55. package/dist/extension/tree/test/human/table-tree-humam.test.d.ts +1 -0
  56. package/dist/extension/tree/test/table-tree-clearDeadNodes.test.d.ts +1 -0
  57. package/dist/extension/tree/test/table-tree-copyNodes.test.d.ts +1 -0
  58. package/dist/extension/tree/test/table-tree-createNodes.test.d.ts +1 -0
  59. package/dist/extension/tree/test/table-tree-deleteNodes.test.d.ts +1 -0
  60. package/dist/extension/tree/test/table-tree-fs-comb.test.d.ts +1 -0
  61. package/dist/extension/tree/test/table-tree-index-comb.test.d.ts +1 -0
  62. package/dist/extension/tree/test/table-tree-listNodes.test.d.ts +1 -0
  63. package/dist/extension/tree/test/table-tree-metadata-comb.test.d.ts +1 -0
  64. package/dist/extension/tree/test/table-tree-moveNodes.test.d.ts +1 -0
  65. package/dist/extension/tree/test/table-tree-multi-user-comb.test.d.ts +1 -0
  66. package/dist/extension/tree/test/table-tree-preOverwriteNodes.test.d.ts +1 -0
  67. package/dist/extension/tree/test/table-tree-presyncNodes.test.d.ts +1 -0
  68. package/dist/extension/tree/test/table-tree-setNdoes.test.d.ts +1 -0
  69. package/dist/extension/tree/test/table-tree-updateNodes.test.d.ts +1 -0
  70. package/dist/extension/tree/test/table-tree.test.d.ts +1 -0
  71. package/dist/extension/tree/test/table-tree.try.d.ts +1 -0
  72. package/dist/extension/tree/tool/clearDeadNodes.d.ts +22 -0
  73. package/dist/extension/tree/tool/refreshTreeMetadata.d.ts +9 -0
  74. package/dist/extension/tree/tree.types.d.ts +111 -0
  75. package/dist/extension/tree/util/applyTreeMetadataDelta.d.ts +29 -0
  76. package/dist/extension/tree/util/assertTreeParent.d.ts +8 -0
  77. package/dist/extension/tree/util/collectAncestorIds.d.ts +4 -0
  78. package/dist/extension/tree/util/collectDescendantNodes.d.ts +10 -0
  79. package/dist/extension/tree/util/collectExistingParentIds.d.ts +9 -0
  80. package/dist/extension/tree/util/collectTopSelectedNodes.d.ts +10 -0
  81. package/dist/extension/tree/util/getNodeValueByPath.d.ts +2 -0
  82. package/dist/extension/tree/util/getUniqueFileNames.d.ts +13 -0
  83. package/dist/extension/tree/util/groupNodesByParentId.d.ts +8 -0
  84. package/dist/extension/tree/util/newEmptyNode.d.ts +2 -0
  85. package/dist/extension/tree/util/newNodeId.d.ts +2 -0
  86. package/dist/extension/tree/util/normalizeWritableNode.d.ts +9 -0
  87. package/dist/extension/tree/util/rebalanceTreeIndexes.d.ts +11 -0
  88. package/dist/extension/tree/util/refreshTreeMetadata.d.ts +16 -0
  89. package/dist/extension/tree/util/repairDuplicatedSiblingConflicts.d.ts +4 -0
  90. package/dist/extension/tree/util/repairDuplicatedSiblingNames.d.ts +4 -0
  91. package/dist/extension/tree/util/repairTreeOverwriteConflicts.d.ts +10 -0
  92. package/dist/extension/tree/util/resolveOverwriteNodes.d.ts +26 -0
  93. package/dist/extension/tree/util/resolveTreeIndex.d.ts +4 -0
  94. package/dist/extension/tree/util/setTreeNumberStat.d.ts +9 -0
  95. package/dist/extension/tree/util/stripTreeManagedFields.d.ts +5 -0
  96. package/dist/index.d.ts +1 -0
  97. package/dist/index.js +4017 -1188
  98. package/dist/test/auto-metadata.test.d.ts +1 -0
  99. package/dist/test/getTestTable.d.ts +3 -1
  100. package/dist/test/globals.d.ts +1 -0
  101. package/dist/test/table-event.test.d.ts +1 -0
  102. package/dist/test/table-index.test.d.ts +1 -0
  103. package/dist/test/table-type.test.d.ts +1 -0
  104. package/dist/test/try/doc.try.d.ts +1 -1
  105. package/dist/test/try/getTestUserTable.d.ts +1 -1
  106. package/dist/test/try/insert.try.d.ts +1 -1
  107. package/dist/test/try/mongodb-try/id-test.d.ts +1 -0
  108. package/dist/test/try//345/210/233/345/273/272350/344/270/207/346/225/260/346/215/256.d.ts +1 -1
  109. package/dist/test/try//346/223/215/344/275/234350/344/270/207/346/225/260/346/215/256.d.ts +1 -1
  110. package/package.json +26 -8
  111. package/dist/rslib-runtime.js +0 -18
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 侧表机制验证测试
3
+ *
4
+ * 此测试文件验证侧表机制的正确性,包括 null/undefined 查询
5
+ *
6
+ * ✅ 已修复的问题:
7
+ * - null/undefined 查询现在使用纯 SQL 实现
8
+ * - 生成的 SQL 正确匹配:字段不存在、字段值为 null、数组包含 null
9
+ *
10
+ * MongoDB 语义说明:
11
+ * - undefined 在存入时会被转换为 null
12
+ * - 查询 { field: null } 应匹配:字段值为 null、字段不存在、数组包含 null
13
+ */
14
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 侧表机制 BUG 测试
3
+ *
4
+ * 目标:找出 SQLiteAdapter 中侧表(Side Table)机制的潜在 BUG
5
+ *
6
+ * 侧表机制说明:
7
+ * - 侧表用于数组字段的倒排索引,存储 (val, id) 对
8
+ * - 使用 SQLite Trigger 在 INSERT/UPDATE/DELETE 时自动维护
9
+ * - 用于加速数组包含查询,如 { tags: "A" } 可以利用侧表实现快速查询
10
+ *
11
+ * 潜在问题:
12
+ * 1. Trigger 使用 NEW.id/OLD.id(用户 ID)进行关联,而非 _id(内部自增 ID)
13
+ * 2. 如果用户 ID 有特殊字符或格式,可能导致查询失败
14
+ * 3. 更新/删除后侧表同步问题
15
+ * 4. 批量操作后侧表重建问题
16
+ */
17
+ export {};
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 侧表机制边界情况 BUG 测试
3
+ *
4
+ * 这些测试针对更极端的边界情况,旨在找出侧表机制中隐藏的 BUG
5
+ *
6
+ * 主要测试点:
7
+ * 1. 数组嵌套层级问题
8
+ * 2. 特殊值(NaN, Infinity, undefined)在数组中的处理
9
+ * 3. 重复元素处理
10
+ * 4. 数组元素顺序变化
11
+ * 5. 大量唯一值的性能和正确性
12
+ * 6. 索引字段不存在或为 undefined
13
+ * 7. 侧表与主表数据不一致检测
14
+ */
15
+ export {};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * SQLiteAdapter 数据类型和边缘情况测试
3
+ * 确保各种 JS 数据类型的序列化/反序列化正确性
4
+ */
5
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * SQLiteAdapter 多驱动测试
3
+ *
4
+ * 测试 SQLiteAdapter 使用不同驱动(better-sqlite3 和 node:sqlite)时的功能一致性
5
+ */
6
+ export {};
@@ -0,0 +1,4 @@
1
+ /**
2
+ * SQLiteAdapter 查询操作符和高级边缘情况测试
3
+ */
4
+ export {};
@@ -7,4 +7,7 @@ export interface ISqlQuery {
7
7
  limit?: number;
8
8
  offset?: number;
9
9
  }
10
- export declare function mongoToSql(filter: ITableFilter, options?: ITableFindOptions): Promise<ISqlQuery>;
10
+ export declare function mongoToSql(filter: ITableFilter, options?: ITableFindOptions, schemaStats?: Map<string, {
11
+ hasArray: boolean;
12
+ hasSpecial: boolean;
13
+ }>): Promise<ISqlQuery>;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 规范化投影参数(数组转对象)
3
+ */
4
+ export declare function normalizeProjection(proj?: string[] | Record<string, 1 | -1 | 0>): Record<string, number> | undefined;
5
+ /**
6
+ * 投影 (Projection) 处理函数
7
+ *
8
+ * 类似于 MongoDB 的 project 逻辑:
9
+ * - 如果指定了包含 (inclusion mode): 只返回指定的字段 + _id (除非显式排除了 _id)。
10
+ * - 如果指定了排除 (exclusion mode): 返回所有字段,除了指定的字段。
11
+ *
12
+ * @param doc 原始文档对象
13
+ * @param projection 投影配置 (e.g. { name: 1, age: 1 } 或 { password: 0 })
14
+ * @returns 投影后的新对象
15
+ */
16
+ export declare function project(doc: any, projection: any): any;
@@ -0,0 +1,54 @@
1
+ import { ITableFilter } from "../../../core/types";
2
+ export interface CompatibilityResult {
3
+ compatible: boolean;
4
+ reasons: Array<{
5
+ path: string;
6
+ reason: string;
7
+ value?: any;
8
+ }>;
9
+ }
10
+ /**
11
+ * 判断值是否可以直接在 SQL 中安全比较
12
+ *
13
+ * 目前支持:
14
+ * - string, boolean (直接 SQL 映射)
15
+ * - number (需要排除 NaN, Infinity)
16
+ * - Date (作为时间戳或 ISO 字符串比较,通常视具体序列化实现而定,这里假设 adapter 处理了)
17
+ *
18
+ * 不支持:
19
+ * - object, array (需要 JSON 解析)
20
+ * - null, undefined (SQL NULL 语义复杂,保守起见可能需要特殊处理)
21
+ * - bigint (可能超出 SQL INTEGER 范围或需要特殊转换)
22
+ */
23
+ export declare function isCompatibleValue(val: any): boolean;
24
+ /**
25
+ * 分析查询兼容性 (Query Compatibility Analysis)
26
+ *
27
+ * 目的:
28
+ * 判断一个 MongoDB 风格的 filter 是否可以完全、等价地转换为一族 SQL WHERE 子句。
29
+ *
30
+ * 策略选择:
31
+ * - 如果 Compatible=true: 使用纯 SQL 查询 (高性能)。
32
+ * - 如果 Compatible=false: 使用混合查询 (Hybrid Mode),即 "SQL 粗筛 + JS 精确匹配"。
33
+ *
34
+ * 不兼容情况 (Incompatible Scenarios):
35
+ * 1. 特殊操作符: $where, $nor (SQL 难以直接表达其短路或逻辑).
36
+ * 2. 数组/对象全量匹配: { tags: ["A", "B"] } (需要严格顺序和内容匹配).
37
+ * 3. 隐式数组包含: { tags: "A" } 且 tags 是数组 (MongoDB 语义是 distinct contains, SQL 默认是 equality).
38
+ * 4. 特殊数值: NaN, Infinity (SQL 标准浮点数处理可能不一致).
39
+ * 5. 深层点号路径: "a.b.c" 涉及中间路径可能是数组的情况 (需要 unwind).
40
+ *
41
+ * @param filter 用户查询对象
42
+ * @param schemaStats 字段统计信息,用于判断某个路径是否曾经存储过数组 (Schema Dirty Tracking).
43
+ */
44
+ export declare function analyzeQueryCompatibility(filter: ITableFilter, schemaStats?: Map<string, {
45
+ hasArray: boolean;
46
+ hasSpecial: boolean;
47
+ }>): CompatibilityResult;
48
+ /**
49
+ * 简化的兼容性判断入口
50
+ */
51
+ export declare function isQuerySqlCompatible(filter: ITableFilter, schemaStats?: Map<string, {
52
+ hasArray: boolean;
53
+ hasSpecial: boolean;
54
+ }>): boolean;
@@ -1,10 +1,27 @@
1
1
  /**
2
+ * 检测 JSON 字符串是否包含特殊类型标记
3
+ * 用于快速判断是否需要完整的反序列化流程
4
+ * @param json JSON 字符串
5
+ * @returns 如果包含特殊类型标记(如 "$t")返回 true,否则返回 false
6
+ */
7
+ export declare function needsSpecialDeserialization(json: string): boolean;
8
+ /**
9
+ * 快速反序列化
10
+ * 如果 JSON 不包含特殊类型,直接使用 JSON.parse
11
+ * 否则使用完整的 deserialize 流程
12
+ */
13
+ export declare function fastDeserialize(json: string): any;
14
+ /**
15
+ * 异步序列化版本
2
16
  * 将 JS 对象序列化为 SQLite 可存储的 JSON 友好格式
3
- * 异步版本:支持 Blob 转 Base64
17
+ * 支持 Blob 转 Base64
4
18
  */
5
19
  export declare function serialize(value: any): Promise<any>;
6
20
  /**
7
- * 同步版本:不支持 Blob (除非 Blob逻辑是sync的,但通常不是)
21
+ * 同步序列化版本
22
+ * 减少异步调用的开销,提高性能
23
+ * 将 JS 对象序列化为 SQLite 可存储的 JSON 友好格式
24
+ * 不支持 Blob,因为 Blob 需要异步读取文件内容
8
25
  * 用于 JsPatch 等同步环境
9
26
  */
10
27
  export declare function serializeSync(value: any): any;
@@ -1,4 +1,4 @@
1
- import { Database } from "better-sqlite3";
1
+ import type { ISqliteDatabase } from "../driver/types";
2
2
  /**
3
3
  * 检查文件是否为 ZSTD 压缩文件 (Magic Number: 0xFD2FB528)
4
4
  */
@@ -8,5 +8,5 @@ export declare function isZstdFile(filepath: string): boolean;
8
8
  * @param filename 数据库文件名
9
9
  */
10
10
  export declare function checkAndDecompressDb(filename: string): void;
11
- export declare function prepareForCompression(db: Database): void;
11
+ export declare function prepareForCompression(db: ISqliteDatabase): void;
12
12
  export declare function compressFile(filename: string): void;
@@ -16,7 +16,9 @@ export interface ITableDBAdapterInstance {
16
16
  set(id: any, value: Partial<ITableDoc>): Promise<void>;
17
17
  delete(id: any): Promise<void>;
18
18
  has(id: any): Promise<boolean>;
19
- count(filter?: ITableFilter): Promise<number>;
19
+ count(filter?: ITableFilter, options?: {
20
+ debug?: ITableDebugResult;
21
+ }): Promise<number>;
20
22
  /** 清空所有数据,不包括索引 */
21
23
  clear(): Promise<void>;
22
24
  /** 清除所有数据和索引 */
@@ -62,7 +64,7 @@ export interface ITableDBAdapterInstance {
62
64
  *
63
65
  * 根据 filter 的匹配结果,可能会删除多个文档
64
66
  */
65
- deleteMany(filter: ITableFilter): Promise<ITableDeletedResult>;
67
+ deleteMany(filter: ITableFilter, options?: ITableDeleteOptions): Promise<ITableDeletedResult>;
66
68
  /** 删除单个文档
67
69
  *
68
70
  * 只会删除第一个匹配的文档
@@ -111,7 +113,7 @@ export interface ITableFindOptions {
111
113
  *
112
114
  * 可以是 plv 预设投影名称
113
115
  */
114
- projection?: string[] | Record<string, 1 | -1>;
116
+ projection?: string[] | Record<string, 1 | -1> | string;
115
117
  /** 排序字段列表
116
118
  *
117
119
  * 可以是字符串数组, 前面加 `-` 表示降序,\
@@ -126,6 +128,9 @@ export interface ITableFindOptions {
126
128
  numericOrdering?: boolean;
127
129
  /** 是否忽略标记删除逻辑,默认 false */
128
130
  ignoreMarkDelete?: boolean;
131
+ /** 调试信息存储对象
132
+ * 提供一个对象用来接受调试信息,调试信息会写入该对象 */
133
+ debug?: ITableDebugResult;
129
134
  }
130
135
  export interface ITableUpdateOptions {
131
136
  /** 是否在没有匹配的文档时插入一个新文档,然后再进行更新操作 */
@@ -137,6 +142,9 @@ export interface ITableUpdateOptions {
137
142
  * 也可以是字段映射对象,1 表示升序,-1 表示降序
138
143
  */
139
144
  sort?: string[] | Record<string, 1 | -1>;
145
+ /** 调试信息存储对象
146
+ * 提供一个对象用来接受调试信息,调试信息会写入该对象 */
147
+ debug?: ITableDebugResult;
140
148
  }
141
149
  export interface ITableDeleteOptions {
142
150
  /** 排序字段列表
@@ -148,6 +156,9 @@ export interface ITableDeleteOptions {
148
156
  sort?: string[] | Record<string, 1 | -1>;
149
157
  /** 是否忽略标记删除逻辑,直接物理删除文档,默认 false */
150
158
  readDelete?: boolean;
159
+ /** 调试信息存储对象
160
+ * 提供一个对象用来接受调试信息,调试信息会写入该对象 */
161
+ debug?: ITableDebugResult;
151
162
  }
152
163
  export interface ITableSetOptions {
153
164
  /** 是否合并对象字段而不是覆盖,默认 false
@@ -162,6 +173,54 @@ export interface ITableSetOptions {
162
173
  insertOnly?: boolean;
163
174
  /** 是否只更新已存在的文档,不存在的文档不进行插入 */
164
175
  updateOnly?: boolean;
176
+ /** 仅在插入新文档时设置的字段
177
+ * 类似于 updateOp 的 $setOnInsert,用于设置 _createDate 等元数据
178
+ */
179
+ setOnInsert?: Record<string, any>;
180
+ /** 调试信息存储对象
181
+ * 提供一个对象用来接受调试信息,调试信息会写入该对象 */
182
+ debug?: ITableDebugResult;
183
+ }
184
+ export interface ITableDebugResult {
185
+ /** SQL 语句及其参数,结构化存储,支持多条(如批量操作或回退查询) */
186
+ sql?: Array<{
187
+ query: string;
188
+ params: any[];
189
+ /** 该条 SQL 的实际执行耗时 (ms) */
190
+ executionTimeMs?: number;
191
+ }>;
192
+ /** EXPLAIN QUERY PLAN 的原始输出 (通常对应最后一条 SQL) */
193
+ sqlPlan?: Array<{
194
+ id: number;
195
+ parent: number;
196
+ detail: string;
197
+ }>;
198
+ /** 适配器总耗时 (ms, 从调用开始到返回) */
199
+ totalTimeMs?: number;
200
+ /** SQL 准备耗时 (ms, mongoToSql 解析 + 序列化开销) */
201
+ prepareTimeMs?: number;
202
+ /** 实际数据库交互总耗时 (ms) */
203
+ dbExecTimeMs?: number;
204
+ /** 查询策略: 'SQL' (纯SQL) | 'HYBRID' (混合) | 'JS' (纯JS兜底) */
205
+ strategy?: "SQL" | "HYBRID" | "JS";
206
+ /** 是否触发了侧表优化 */
207
+ isSideTableUsed?: boolean;
208
+ /** 具体的索引使用情况 (如果有) */
209
+ usedIndexes?: string[];
210
+ /** 导致无法使用纯 SQL 的原因列表 (替换 dirtyQueries) */
211
+ dirtyReasons?: Array<{
212
+ /** 字段路径 */
213
+ path: string;
214
+ /** 原因 (e.g., "Array containment", "$where operator") */
215
+ reason: string;
216
+ /** 导致问题的值 */
217
+ value?: any;
218
+ }>;
219
+ /** 是否全表扫描 (从 sqlPlan 分析得出) */
220
+ isFullScan?: boolean;
221
+ /** 事务状态 */
222
+ isTransaction?: boolean;
223
+ [key: string]: any;
165
224
  }
166
225
  export interface ITableDefineIndexesOptions {
167
226
  /** 是否强制重新创建索引,默认 false */
@@ -0,0 +1 @@
1
+ export {};
@@ -1,9 +1,10 @@
1
+ import { EventHub } from "fzz";
1
2
  import { ITableDBAdapterInstance, ITableDBAdapter, ITableDefineIndexesOptions, ITableDeletedResult, ITableDeleteOptions, ITableDoc, ITableFindOptions, ITableIndexConfig, ITableInsertResult, ITableSetOptions, ITableSetResult, ITableUpdateOptions, ITableUpdateResult } from "../adapter/adapter";
2
3
  import { exportBinary, exportBinaryToFile, importBinary, importBinaryFromFile } from "./backup";
3
- import { __check_filter, __check_find_options, __check_input_doc, __check_output_doc, __check_update_op } from "./check";
4
4
  import { ICursorPagingOptions, IReCursorPaging, IReSkipPaging, ISkipPagingOptions } from "./list";
5
- import { __schema_init, ISchemaHints } from "./schema";
5
+ import { ISchemaHints } from "./schema";
6
6
  import { ITableFilter, ITableUpdateOp } from "./types";
7
+ import { TableEeventDefifne } from "./event";
7
8
  export interface ITableOptions<TSchema, TPlv extends IPlvMap = IPlvMap> {
8
9
  /** Talbe 名称
9
10
  *
@@ -24,6 +25,8 @@ export interface ITableOptions<TSchema, TPlv extends IPlvMap = IPlvMap> {
24
25
  adapter?: ITableDBAdapter;
25
26
  /** 是否启用标记删除功能 */
26
27
  enableMarkDelete?: boolean;
28
+ /** 是否启用自动元数据功能(_updateDate, _createDate, _deleteDate) */
29
+ enableAutoMetadata?: boolean;
27
30
  /** 是否启用目录树功能 */
28
31
  enableTree?: boolean;
29
32
  /** 预设投影列表 */
@@ -51,15 +54,16 @@ export declare class Table<TSchema extends ITableDoc = ITableDoc, TPlv extends I
51
54
  adapter: ITableDBAdapterInstance;
52
55
  schema: TSchema;
53
56
  inited: Promise<boolean>;
57
+ eventHub: EventHub<typeof TableEeventDefifne>;
54
58
  constructor(tableOptions: ITableOptions<TSchema, TPlv>);
55
59
  init(): Promise<boolean>;
56
60
  __schema_hints: ISchemaHints;
57
- __schema_init: typeof __schema_init;
58
- __check_filter: typeof __check_filter;
59
- __check_output_doc: typeof __check_output_doc;
60
- __check_find_options: typeof __check_find_options;
61
- __check_input_doc: typeof __check_input_doc;
62
- __check_update_op: typeof __check_update_op;
61
+ private __schema_init;
62
+ private __check_filter;
63
+ private __check_output_doc;
64
+ private __check_find_options;
65
+ private __check_input_doc;
66
+ private __check_update_op;
63
67
  /** 获取单个文档 */
64
68
  get(id: any, options?: ITableGetBaseOptions): Promise<TSchema | void>;
65
69
  /** 设置单个文档 */
@@ -69,7 +73,9 @@ export declare class Table<TSchema extends ITableDoc = ITableDoc, TPlv extends I
69
73
  /** 检查单个文档是否存在 */
70
74
  has(id: any, options?: ITableGetBaseOptions): Promise<boolean>;
71
75
  /** 统计文档数量 */
72
- count(filter?: ITableFilter, options?: ITableGetBaseOptions): Promise<number>;
76
+ count(filter?: ITableFilter, options?: ITableGetBaseOptions & {
77
+ debug?: any;
78
+ }): Promise<number>;
73
79
  /** 清空所有文档 */
74
80
  clear(): Promise<void>;
75
81
  /** 清除所有文档和索引 */
@@ -18,9 +18,15 @@ import { ITableOptions, Table } from "./Table";
18
18
  * // 如果要指定 adapter
19
19
  * const useCustomTable = defineTable({adapter : SQLiteAdapter({filename: ":memory:"})})
20
20
  */
21
- export declare function defineTable<TSchema extends ITableDoc = ITableDoc>(tableOptions: ITableOptions<TSchema>): UseTalbeFunction<TSchema>;
22
- export type UseTalbeFunction<TSchema extends ITableDoc = ITableDoc> = (opitons?: {
21
+ export declare function defineTable<TSchema extends ITableDoc = ITableDoc, TTable extends Table<TSchema> = Table<TSchema>>(tableOptions: ITableOptions<TSchema>, TableClass?: new (options: ITableOptions<TSchema>) => TTable): UseTableFunction<TSchema, TTable>;
22
+ /** 兼容旧的拼写错误类型 */
23
+ export type UseTalbeFunction<TSchema extends ITableDoc = ITableDoc, TTable extends Table<TSchema> = Table<TSchema>> = UseTableFunction<TSchema, TTable>;
24
+ /** 定义使用 Table 函数的类型 */
25
+ export type UseTableFunction<TSchema extends ITableDoc = ITableDoc, TTable extends Table<TSchema> = Table<TSchema>> = (options?: {
23
26
  adapter?: ITableDBAdapter;
24
- }) => Promise<Table<TSchema>>;
25
- /** 定义全局的数据库适配器(SQLite/MongoDB) */
27
+ }) => Promise<TTable>;
28
+ /** 定义全局的数据库适配器(SQLite/MongoDB)
29
+ *
30
+ * @param adapter 数据库适配器实例
31
+ */
26
32
  export declare function defineGlobalDBAdapter(adapter: ITableDBAdapter): void;
@@ -0,0 +1,24 @@
1
+ import { ITableFilter, ITableUpdateOp } from "./types";
2
+ import { ITableDoc } from "../adapter/adapter";
3
+ export declare const TableEeventDefifne: {
4
+ CheckFilter: {
5
+ filter: ITableFilter;
6
+ options?: {
7
+ ignoreMarkDelete?: boolean;
8
+ realDelete?: boolean;
9
+ } & Record<string, any>;
10
+ };
11
+ CheckInputDoc: Partial<ITableDoc> | void;
12
+ CheckFindOptions: {
13
+ projection?: any;
14
+ };
15
+ CheckOutputDoc: Partial<ITableDoc> | void;
16
+ CheckUpdateOp: ITableUpdateOp | void;
17
+ };
18
+ export declare const TabeEvents: {
19
+ CheckFilter: "CheckFilter";
20
+ CheckInputDoc: "CheckInputDoc";
21
+ CheckFindOptions: "CheckFindOptions";
22
+ CheckOutputDoc: "CheckOutputDoc";
23
+ CheckUpdateOp: "CheckUpdateOp";
24
+ };
@@ -2,7 +2,7 @@ import { ITableDoc } from "../adapter/adapter";
2
2
  /** Table 的基本类型
3
3
  * 这格式可以直接存入 Table 后取出时,类型不会变化,Table 会保持其原始类型
4
4
  */
5
- export type ITablePrimitive = string | number | boolean | null | undefined | Date | RegExp | Map<any, any> | Set<any> | bigint | Blob | File | ArrayBuffer | DataView | Int8Array | Int16Array | Int32Array | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
5
+ export type ITablePrimitive = string | number | boolean | null | undefined | Date | RegExp | Map<any, any> | Set<any> | bigint | Blob | File | ArrayBuffer | DataView | Int8Array | Int16Array | Int32Array | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array | Error;
6
6
  /**
7
7
  * Table 的数据类型,可以是基本类型、对象或数组
8
8
  *
@@ -0,0 +1,49 @@
1
+ import { Table, ITableOptions } from "../../core/Table";
2
+ import { ITreeNode } from "./tree.types";
3
+ import { createNodes } from "./core/createNodes";
4
+ import { updateNodes } from "./core/updateNodes";
5
+ import { setNodes } from "./core/setNodes";
6
+ import { deleteNodes } from "./core/deleteNodes";
7
+ import { unDeleteNodes } from "./core/unDeleteNodes";
8
+ import { moveNodes } from "./core/moveNodes";
9
+ import { copyNodes } from "./core/copyNodes";
10
+ import { listNodes } from "./core/listNodes";
11
+ import { listNodesByCursor } from "./core/listNodesByCursor";
12
+ import { preOverwriteNodes } from "./core/preOverwriteNodes";
13
+ import { presyncNodes } from "./core/presyncNodes";
14
+ import { UseTableFunction } from "../../core/defineTable";
15
+ /**
16
+ * 目录树表
17
+ * 预置了常用的树形结构操作方法,如创建节点、删除节点、更新节点等
18
+ * 每个文档被视为一个节点,必须包含 parentId 字段来表示父子关系
19
+ * 会自动维护节点的层级关系和修改标记
20
+ *
21
+ */
22
+ export declare class TableTree<TNode extends ITreeNode = ITreeNode> extends Table<TNode> {
23
+ createNodes: typeof createNodes;
24
+ updateNodes: typeof updateNodes;
25
+ setNodes: typeof setNodes;
26
+ deleteNodes: typeof deleteNodes;
27
+ unDeleteNodes: typeof unDeleteNodes;
28
+ moveNodes: typeof moveNodes;
29
+ copyNodes: typeof copyNodes;
30
+ listNodes: typeof listNodes;
31
+ listNodesByCursor: typeof listNodesByCursor;
32
+ preOverwriteNodes: typeof preOverwriteNodes;
33
+ presyncNodes: typeof presyncNodes;
34
+ }
35
+ /**
36
+ * 定义目录树表,返回一个 useTableTree 函数
37
+ *
38
+ * @param tableOptions TableTree 的配置选项
39
+ * @returns 返回一个异步获取 TableTree 实例的函数
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * const useFileTree = defineTableTree<ZFile>({
44
+ * name: "file-tree",
45
+ * })
46
+ * const fileTree = await useFileTree()
47
+ * ```
48
+ */
49
+ export declare function defineTableTree<TNode extends ITreeNode = ITreeNode>(tableOptions: ITableOptions<TNode>): UseTableFunction<TNode, TableTree<TNode>>;
@@ -0,0 +1,36 @@
1
+ import type { TableTree } from "../TableTree";
2
+ import type { ITreeIndexOptions, ITreeNode, ITreeOverwriteOptions } from "../tree.types";
3
+ /** 复制节点选项 */
4
+ export type ITreeCopyNodesOptions = ITreeOverwriteOptions & {
5
+ /** 是否自动计算并写入排序索引 */
6
+ index?: ITreeIndexOptions;
7
+ /** 是否递归复制子节点 */
8
+ deep?: boolean;
9
+ /** 复制后的节点是否自动重命名
10
+ * 使用 getUniqueFileNames() 获得独特名字
11
+ */
12
+ renameOnCopy?: boolean;
13
+ };
14
+ export interface ITreeCopyResult {
15
+ /** 创建的节点 id 列表(如果有递归,不算子文件,只有 `srcNodeIds` 对应复制的节点) */
16
+ createdNodeIds: string[];
17
+ }
18
+ /**
19
+ * 复制节点
20
+ *
21
+ * 将已存在节点复制到目标父级,并为复制出的每个节点生成新的 ID。
22
+ *
23
+ * 核心流程:
24
+ * 1. 去重并读取源节点,父子混合选择时只保留最外层源节点,避免子节点被重复复制。
25
+ * 2. 按 renameOnCopy 规则为顶层副本预生成名称;默认复制到同级时自动避让重名。
26
+ * 3. 递归构造待写入节点列表,deep 模式下复制整棵子树,所有副本共享本次复制的 modif。
27
+ * 4. 只给顶层副本计算目标父级下的 index,子节点在各自新父级下保持构造顺序。
28
+ * 5. 交给 setNodes 统一处理覆盖策略、metadata、标记删除恢复和最终写入。
29
+ * 6. 返回仍然可见的顶层副本 ID;如果覆盖策略跳过了某些副本,它们不会出现在结果里。
30
+ *
31
+ */
32
+ export declare function copyNodes(this: TableTree<ITreeNode>,
33
+ /** 待复制的源节点 ID 列表 */
34
+ srcNodeIds: string[],
35
+ /** 目标父节点 ID,如果为 "/" 表示根节点 */
36
+ parentId: string, options?: ITreeCopyNodesOptions): Promise<ITreeCopyResult>;
@@ -0,0 +1,33 @@
1
+ import type { TableTree } from "../TableTree";
2
+ import type { ITreeNode, ITreeIndexOptions } from "../tree.types";
3
+ /** 创建节点选项 */
4
+ export interface ITreeCreateNodesOptions {
5
+ /** 是否自动计算并写入排序索引 */
6
+ index?: ITreeIndexOptions;
7
+ /** 是否在创建后返回新节点的数据,默认为 false */
8
+ returnNewNodes?: boolean;
9
+ }
10
+ export interface ITreeCreateResult {
11
+ /** 创建的节点 id 列表 */
12
+ createdNodeIds: string[];
13
+ /** 创建的节点数据列表,仅在 options.returnNewNodes 为 true 时返回 */
14
+ newNodes?: ITreeNode[];
15
+ }
16
+ /**
17
+ * 创建节点
18
+ *
19
+ * 在指定父级下批量插入新节点,并维护目录树需要的排序和统计字段。
20
+ *
21
+ * 核心流程:
22
+ * 1. 先校验父级是否存在,避免写入孤儿节点。
23
+ * 2. 将外部传入的 Partial 节点归一化为完整可写节点,并统一本次操作的 modif。
24
+ * 3. 根据显式 index 选项或父级当前排序状态,为缺少 index 的节点补齐排序值。
25
+ * 4. 调用底层 insertMany 写入;如果遇到重复 ID,底层会跳过,所以后续只处理实际插入成功的节点。
26
+ * 5. 用实际插入节点的贡献量增量刷新父级及祖先 metadata,并按需触发 index 智能重排。
27
+ *
28
+ */
29
+ export declare function createNodes(this: TableTree<ITreeNode>,
30
+ /** 要创建的节点文档 */
31
+ nodes: Partial<ITreeNode>[],
32
+ /** 父级节点 id ,如果为 "/" 表示根节点 */
33
+ parentId: string, options?: ITreeCreateNodesOptions): Promise<ITreeCreateResult>;
@@ -0,0 +1,33 @@
1
+ import type { TableTree } from "../TableTree";
2
+ import type { ITreeNode } from "../tree.types";
3
+ /** 删除节点选项 */
4
+ export interface ITreeDeleteNodesOptions {
5
+ /** 是否强制物理删除 */
6
+ realDelete?: boolean;
7
+ }
8
+ /** 删除节点结果 */
9
+ export interface ITreeDeleteResult {
10
+ /** 是否有节点被删除 */
11
+ hasDeleted: boolean;
12
+ /** 是否有子节点被删除 */
13
+ hasChildDeleted: boolean;
14
+ /** 被删除的节点数量 */
15
+ deletedCount: number;
16
+ }
17
+ /**
18
+ * 删除节点
19
+ *
20
+ * 删除指定节点及其全部后代。
21
+ *
22
+ * 核心流程:
23
+ * 1. 去重输入 ID,并读取这些节点连同所有后代,确保目录删除会覆盖整棵子树。
24
+ * 2. 计算“最外层被删除节点”,父子同时删除时只用父节点扣减 metadata,避免后代重复扣减。
25
+ * 3. 根据 TableTree 的标记删除配置选择物理删除或软删除;软删除会写入统一 modif。
26
+ * 4. 用最外层节点对父级的贡献量做负增量,刷新父级及祖先的统计和 childLastIndex。
27
+ *
28
+ * 要注意递归删除可能会导致性能问题,尤其是当删除的节点有大量子孙节点时。
29
+ *
30
+ */
31
+ export declare function deleteNodes(this: TableTree<ITreeNode>,
32
+ /** 要删除的节点 id 列表 */
33
+ nodeIds: string[], options?: ITreeDeleteNodesOptions): Promise<ITreeDeleteResult>;
@@ -0,0 +1,32 @@
1
+ import type { TableTree } from "../TableTree";
2
+ import type { ITableFilter } from "../../../core/types";
3
+ import type { ITreeNode } from "../tree.types";
4
+ import type { IReSkipPaging, ISkipPagingOptions } from "../../../core/list";
5
+ /** 子节点分页查询选项(skip/limit) */
6
+ export interface ITreeListNodesOptions extends ISkipPagingOptions {
7
+ /** 仅返回指定类型的节点(优先级高于 onlyNotTypes) */
8
+ onlyTypes?: string[];
9
+ /** 排除指定类型的节点 */
10
+ onlyNotTypes?: string[];
11
+ /** 是否忽略标记删除(结果包括被标记删除的节点) */
12
+ ignoreMarkDelete?: boolean;
13
+ /** 额外的 filter,可以手动指定更多的限定范围以提高性能 */
14
+ filter?: ITableFilter;
15
+ }
16
+ /** 子节点分页查询结果(skip/limit) */
17
+ export type ITreeListNodesResult<TNode extends ITreeNode = ITreeNode> = IReSkipPaging<TNode>;
18
+ /**
19
+ * 列出节点列表(skip/limit 分页)
20
+ *
21
+ * 获取指定父级的直属子节点。
22
+ *
23
+ * 核心流程:
24
+ * 1. 先通过 buildTreeListFilter 固定 parentId,确保额外 filter 不能越权查询其他父级。
25
+ * 2. 根据 onlyTypes / onlyNotTypes 追加类型过滤,onlyTypes 优先级更高。
26
+ * 3. 默认按 index 升序返回,符合目录树手动排序语义;调用方仍可通过 options.sort 覆盖。
27
+ * 4. 将 ignoreMarkDelete 透传给底层分页,让调用方可选择是否读取软删除节点。
28
+ */
29
+ export declare function listNodes(this: TableTree<ITreeNode>,
30
+ /** 要获取的节点,可以用 '/' 表示根节点 */
31
+ parentId: string, options?: ITreeListNodesOptions): Promise<ITreeListNodesResult<ITreeNode>>;
32
+ export declare function buildTreeListFilter(parentId: string, options?: ITreeListNodesOptions): ITableFilter;
@@ -0,0 +1,31 @@
1
+ import { ICursorPagingOptions, IReCursorPaging } from "../../../core/list";
2
+ import { ITableFilter } from "../../../core/types";
3
+ import { TableTree } from "../TableTree";
4
+ import { ITreeNode } from "../tree.types";
5
+ /** 子节点分页查询选项(cursor) */
6
+ export interface ITreeListNodesByCursorOptions extends ICursorPagingOptions {
7
+ /** 仅返回指定类型的节点(优先级高于 onlyNotTypes) */
8
+ onlyTypes?: string[];
9
+ /** 排除指定类型的节点 */
10
+ onlyNotTypes?: string[];
11
+ /** 是否忽略标记删除(结果包括被标记删除的节点) */
12
+ ignoreMarkDelete?: boolean;
13
+ /** 额外的 filter,可以手动指定更多的限定范围以提高性能 */
14
+ filter?: ITableFilter;
15
+ }
16
+ /** 子节点分页查询结果(cursor) */
17
+ export type ITreeListNodesByCursorResult<TNode extends ITreeNode = ITreeNode> = IReCursorPaging<TNode>;
18
+ /**
19
+ * 列出节点列表(游标分页)
20
+ *
21
+ * 获取指定父级的直属子节点,适合“继续加载下一页”的场景。
22
+ *
23
+ * 核心流程:
24
+ * 1. 复用 buildTreeListFilter,保证父级限定和类型过滤与 listNodes 完全一致。
25
+ * 2. 使用底层 listPagingByCursor 实现游标分页,避免大页码 skip 的性能问题。
26
+ * 3. 默认 sortKey 为 id,sortOrder 为升序;调用方可以显式指定其他游标排序字段。
27
+ * 4. 透传 ignoreMarkDelete,保持软删除读取语义与 skip/limit 分页一致。
28
+ */
29
+ export declare function listNodesByCursor(this: TableTree<ITreeNode>,
30
+ /** 要获取的节点,可以用 '/' 表示根节点 */
31
+ parentId: string, options?: ITreeListNodesByCursorOptions): Promise<ITreeListNodesByCursorResult<ITreeNode>>;