@yydb/light-db 0.0.18 → 0.1.2

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 (110) hide show
  1. package/dist/api/index.d.ts +4 -9
  2. package/dist/api/index.d.ts.map +1 -1
  3. package/dist/api/index.js +3 -6
  4. package/dist/api/index.js.map +1 -1
  5. package/dist/api/types.d.ts +71 -42
  6. package/dist/api/types.d.ts.map +1 -1
  7. package/dist/api/types.js +5 -3
  8. package/dist/api/types.js.map +1 -1
  9. package/dist/api/wasm-database.d.ts +134 -27
  10. package/dist/api/wasm-database.d.ts.map +1 -1
  11. package/dist/api/wasm-database.js +172 -28
  12. package/dist/api/wasm-database.js.map +1 -1
  13. package/dist/index.d.ts +14 -11
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +14 -11
  16. package/dist/index.js.map +1 -1
  17. package/dist/shared/micro.d.ts +86 -0
  18. package/dist/shared/micro.d.ts.map +1 -0
  19. package/dist/shared/micro.js +194 -0
  20. package/dist/shared/micro.js.map +1 -0
  21. package/dist/shared/udf-types.d.ts +31 -0
  22. package/dist/shared/udf-types.d.ts.map +1 -0
  23. package/dist/shared/udf-types.js +12 -0
  24. package/dist/shared/udf-types.js.map +1 -0
  25. package/package.json +5 -7
  26. package/readme.md +60 -63
  27. package/dist/api/database.d.ts +0 -101
  28. package/dist/api/database.d.ts.map +0 -1
  29. package/dist/api/database.js +0 -149
  30. package/dist/api/database.js.map +0 -1
  31. package/dist/api/schema.d.ts +0 -33
  32. package/dist/api/schema.d.ts.map +0 -1
  33. package/dist/api/schema.js +0 -80
  34. package/dist/api/schema.js.map +0 -1
  35. package/dist/api/transaction.d.ts +0 -26
  36. package/dist/api/transaction.d.ts.map +0 -1
  37. package/dist/api/transaction.js +0 -52
  38. package/dist/api/transaction.js.map +0 -1
  39. package/dist/codec/binary.d.ts +0 -196
  40. package/dist/codec/binary.d.ts.map +0 -1
  41. package/dist/codec/binary.js +0 -342
  42. package/dist/codec/binary.js.map +0 -1
  43. package/dist/codec/checksum.d.ts +0 -21
  44. package/dist/codec/checksum.d.ts.map +0 -1
  45. package/dist/codec/checksum.js +0 -46
  46. package/dist/codec/checksum.js.map +0 -1
  47. package/dist/codec/index.d.ts +0 -12
  48. package/dist/codec/index.d.ts.map +0 -1
  49. package/dist/codec/index.js +0 -10
  50. package/dist/codec/index.js.map +0 -1
  51. package/dist/codec/page.d.ts +0 -114
  52. package/dist/codec/page.d.ts.map +0 -1
  53. package/dist/codec/page.js +0 -225
  54. package/dist/codec/page.js.map +0 -1
  55. package/dist/codec/record.d.ts +0 -62
  56. package/dist/codec/record.d.ts.map +0 -1
  57. package/dist/codec/record.js +0 -82
  58. package/dist/codec/record.js.map +0 -1
  59. package/dist/core/broadcast.d.ts +0 -39
  60. package/dist/core/broadcast.d.ts.map +0 -1
  61. package/dist/core/broadcast.js +0 -54
  62. package/dist/core/broadcast.js.map +0 -1
  63. package/dist/core/checkpoint.d.ts +0 -23
  64. package/dist/core/checkpoint.d.ts.map +0 -1
  65. package/dist/core/checkpoint.js +0 -49
  66. package/dist/core/checkpoint.js.map +0 -1
  67. package/dist/core/engine.d.ts +0 -142
  68. package/dist/core/engine.d.ts.map +0 -1
  69. package/dist/core/engine.js +0 -304
  70. package/dist/core/engine.js.map +0 -1
  71. package/dist/core/index.d.ts +0 -17
  72. package/dist/core/index.d.ts.map +0 -1
  73. package/dist/core/index.js +0 -13
  74. package/dist/core/index.js.map +0 -1
  75. package/dist/core/lease.d.ts +0 -32
  76. package/dist/core/lease.d.ts.map +0 -1
  77. package/dist/core/lease.js +0 -81
  78. package/dist/core/lease.js.map +0 -1
  79. package/dist/core/records.d.ts +0 -49
  80. package/dist/core/records.d.ts.map +0 -1
  81. package/dist/core/records.js +0 -70
  82. package/dist/core/records.js.map +0 -1
  83. package/dist/core/recovery.d.ts +0 -43
  84. package/dist/core/recovery.d.ts.map +0 -1
  85. package/dist/core/recovery.js +0 -99
  86. package/dist/core/recovery.js.map +0 -1
  87. package/dist/core/wal.d.ts +0 -50
  88. package/dist/core/wal.d.ts.map +0 -1
  89. package/dist/core/wal.js +0 -114
  90. package/dist/core/wal.js.map +0 -1
  91. package/dist/storage/StorageAdapter.d.ts +0 -97
  92. package/dist/storage/StorageAdapter.d.ts.map +0 -1
  93. package/dist/storage/StorageAdapter.js +0 -9
  94. package/dist/storage/StorageAdapter.js.map +0 -1
  95. package/dist/storage/index.d.ts +0 -11
  96. package/dist/storage/index.d.ts.map +0 -1
  97. package/dist/storage/index.js +0 -10
  98. package/dist/storage/index.js.map +0 -1
  99. package/dist/storage/indexeddb/IndexedDbStorageAdapter.d.ts +0 -140
  100. package/dist/storage/indexeddb/IndexedDbStorageAdapter.d.ts.map +0 -1
  101. package/dist/storage/indexeddb/IndexedDbStorageAdapter.js +0 -403
  102. package/dist/storage/indexeddb/IndexedDbStorageAdapter.js.map +0 -1
  103. package/dist/storage/memory/MemoryStorageAdapter.d.ts +0 -76
  104. package/dist/storage/memory/MemoryStorageAdapter.d.ts.map +0 -1
  105. package/dist/storage/memory/MemoryStorageAdapter.js +0 -212
  106. package/dist/storage/memory/MemoryStorageAdapter.js.map +0 -1
  107. package/dist/storage/opfs/OpfsStorageAdapter.d.ts +0 -141
  108. package/dist/storage/opfs/OpfsStorageAdapter.d.ts.map +0 -1
  109. package/dist/storage/opfs/OpfsStorageAdapter.js +0 -400
  110. package/dist/storage/opfs/OpfsStorageAdapter.js.map +0 -1
@@ -1,149 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Pure-TS Database (StorageEngine wrapper — browser-friendly, no WASM)
3
- // ---------------------------------------------------------------------------
4
- import { StorageEngine } from '../core/engine.js';
5
- import { LightDbError, LightDbErrorCodes } from '../errors/index.js';
6
- import { isOpfsAvailable, OpfsStorageAdapterFactory } from '../storage/opfs/OpfsStorageAdapter.js';
7
- import { decodeSchema, encodeSchema, parseSchemaDocument, RESERVED_KEY_PREFIX, SCHEMA_KEY } from './schema.js';
8
- import { Transaction } from './transaction.js';
9
- /** 数据库名最大长度 */
10
- const MAX_DATABASE_NAME_LENGTH = 128;
11
- /**
12
- * 浏览器可用的纯 TS 数据库实现。
13
- *
14
- * 与 Node 侧 `@yydb/yydb` 的 {@link Database} 同构:宿主靠 import 来源区分:
15
- *
16
- * ```ts
17
- * import { Database } from '@yydb/yydb'; // Node 原生
18
- * import { Database } from '@yydb/light-db'; // 浏览器纯 TS(本文件)
19
- * ```
20
- *
21
- * 完全不依赖 WASM;OPFS 持久化、WAL 恢复、检查点、事务都在 TypeScript 内完成。
22
- *
23
- * 默认后端是 `OpfsStorageAdapterFactory`;通过 `options.storage` 可以显式指定。
24
- */
25
- export class Database {
26
- /** 数据库名 */
27
- name;
28
- engine;
29
- transaction;
30
- constructor(name, engine) {
31
- this.name = name;
32
- this.engine = engine;
33
- this.transaction = new Transaction(engine);
34
- }
35
- /**
36
- * 打开数据库
37
- * @param name 数据库名
38
- * @param options 打开选项
39
- */
40
- static async open(name, options = {}) {
41
- if (name.trim().length === 0 || name.length > MAX_DATABASE_NAME_LENGTH) {
42
- throw new LightDbError(LightDbErrorCodes.unsupported, `database name must be 1-${MAX_DATABASE_NAME_LENGTH} characters`, {
43
- operation: 'open',
44
- });
45
- }
46
- const storage = resolveStorageFactory(options);
47
- const engineOptions = {};
48
- if (options.pageSize !== undefined)
49
- engineOptions.pageSize = options.pageSize;
50
- if (options.walThreshold !== undefined)
51
- engineOptions.walThreshold = options.walThreshold;
52
- if (options.autoCheckpoint !== undefined)
53
- engineOptions.autoCheckpoint = options.autoCheckpoint;
54
- if (options.lease !== undefined)
55
- engineOptions.lease = options.lease;
56
- const engine = await StorageEngine.open(name, storage, engineOptions);
57
- return new Database(name, engine);
58
- }
59
- /** 读取已持久化的 schema */
60
- async schema() {
61
- const value = await this.engine.get(SCHEMA_KEY);
62
- return value ? decodeSchema(value) : null;
63
- }
64
- /**
65
- * 声明 schema 文档
66
- *
67
- * 文档是唯一真相:首次写入后,重复调用必须传入完全相同的文档。
68
- */
69
- async ensureSchema(document) {
70
- const version = parseSchemaDocument(document);
71
- const existing = await this.schema();
72
- if (existing) {
73
- if (existing.document !== document) {
74
- throw new LightDbError(LightDbErrorCodes.schemaConflict, `schema document conflict: stored version ${existing.version}, incoming version ${version}`, { operation: 'ensureSchema' });
75
- }
76
- return;
77
- }
78
- await this.engine.put(SCHEMA_KEY, encodeSchema({ version, document }));
79
- this.engine.notifySchemaChange();
80
- }
81
- /** 读取键 */
82
- async get(key) {
83
- return this.engine.get(this.assertUserKey(key, 'kvGet'));
84
- }
85
- /** 写入键 */
86
- async put(key, value) {
87
- await this.engine.put(this.assertUserKey(key, 'kvPut'), value);
88
- }
89
- /** 删除键 */
90
- async delete(key) {
91
- return this.engine.delete(this.assertUserKey(key, 'kvDelete'));
92
- }
93
- /** 开始事务 */
94
- async begin() {
95
- await this.transaction.begin();
96
- }
97
- /** 提交事务 */
98
- async commit() {
99
- await this.transaction.commit();
100
- }
101
- /** 回滚事务 */
102
- async rollback() {
103
- await this.transaction.rollback();
104
- }
105
- /** 执行检查点 */
106
- async checkpoint() {
107
- return this.engine.checkpoint();
108
- }
109
- /** 统计信息 */
110
- stats() {
111
- return this.engine.getStats();
112
- }
113
- /** 关闭数据库 */
114
- async close() {
115
- if (this.transaction.isActive) {
116
- await this.transaction.rollback();
117
- }
118
- await this.engine.close();
119
- }
120
- /**
121
- * 校验用户键
122
- */
123
- assertUserKey(key, operation) {
124
- if (key.length === 0) {
125
- throw new LightDbError(LightDbErrorCodes.unsupported, 'key must not be empty', { operation });
126
- }
127
- if (key.startsWith(RESERVED_KEY_PREFIX)) {
128
- throw new LightDbError(LightDbErrorCodes.unsupported, `key prefix "${RESERVED_KEY_PREFIX}" is reserved for the database`, {
129
- operation,
130
- });
131
- }
132
- return key;
133
- }
134
- }
135
- /**
136
- * 解析存储后端
137
- */
138
- function resolveStorageFactory(options) {
139
- if (options.storage) {
140
- return options.storage;
141
- }
142
- if (!isOpfsAvailable()) {
143
- throw new LightDbError(LightDbErrorCodes.unsupported, 'OPFS is unavailable, pass an explicit storage adapter', {
144
- operation: 'open',
145
- });
146
- }
147
- return new OpfsStorageAdapterFactory();
148
- }
149
- //# sourceMappingURL=database.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/api/database.ts"],"names":[],"mappings":"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"}
@@ -1,33 +0,0 @@
1
- /**
2
- * Schema 语义
3
- *
4
- * 与 `@yydb/yydb` 的 Rust 实现同构:Schema 文档是唯一真相,
5
- * 版本由文档前导注释 `// @yydb-schema-version: <n>` 决定,默认 1。
6
- */
7
- import type { SchemaVersion } from './types';
8
- /** Schema 记录在数据库中的保留键 */
9
- export declare const SCHEMA_KEY = "__yydb__/schema";
10
- /** 用户键禁止使用的内部前缀 */
11
- export declare const RESERVED_KEY_PREFIX = "__yydb__/";
12
- /**
13
- * 从文档中提取版本
14
- * @param document Schema 文档
15
- */
16
- export declare function documentVersion(document: string): number;
17
- /**
18
- * 校验 Schema 文档
19
- * @param document Schema 文档
20
- * @returns 文档声明的版本
21
- */
22
- export declare function parseSchemaDocument(document: string): number;
23
- /**
24
- * 编码 Schema 记录
25
- * @param schema Schema 版本与文档
26
- */
27
- export declare function encodeSchema(schema: SchemaVersion): Uint8Array;
28
- /**
29
- * 解码 Schema 记录
30
- * @param value 记录值
31
- */
32
- export declare function decodeSchema(value: Uint8Array): SchemaVersion;
33
- //# sourceMappingURL=schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/api/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,yBAAyB;AACzB,eAAO,MAAM,UAAU,oBAAoB,CAAC;AAE5C,mBAAmB;AACnB,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAK/C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO5D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAE9D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,CAkB7D"}
@@ -1,80 +0,0 @@
1
- /**
2
- * Schema 语义
3
- *
4
- * 与 `@yydb/yydb` 的 Rust 实现同构:Schema 文档是唯一真相,
5
- * 版本由文档前导注释 `// @yydb-schema-version: <n>` 决定,默认 1。
6
- */
7
- import { BinaryUtils } from '../codec';
8
- import { LightDbError, LightDbErrorCodes } from '../errors';
9
- /** Schema 记录在数据库中的保留键 */
10
- export const SCHEMA_KEY = '__yydb__/schema';
11
- /** 用户键禁止使用的内部前缀 */
12
- export const RESERVED_KEY_PREFIX = '__yydb__/';
13
- /** 版本声明注释 */
14
- const VERSION_PRAGMA = /^\s*\/\/\s*@yydb-schema-version:\s*(\d+)\s*$/m;
15
- /**
16
- * 从文档中提取版本
17
- * @param document Schema 文档
18
- */
19
- export function documentVersion(document) {
20
- const match = VERSION_PRAGMA.exec(document);
21
- if (!match) {
22
- return 1;
23
- }
24
- const version = Number.parseInt(match[1], 10);
25
- return Number.isFinite(version) && version > 0 ? version : 1;
26
- }
27
- /**
28
- * 校验 Schema 文档
29
- * @param document Schema 文档
30
- * @returns 文档声明的版本
31
- */
32
- export function parseSchemaDocument(document) {
33
- if (document.trim().length === 0) {
34
- throw new LightDbError(LightDbErrorCodes.schemaInvalid, 'schema document must not be empty', {
35
- operation: 'ensureSchema',
36
- });
37
- }
38
- return documentVersion(document);
39
- }
40
- /**
41
- * 编码 Schema 记录
42
- * @param schema Schema 版本与文档
43
- */
44
- export function encodeSchema(schema) {
45
- return BinaryUtils.encode(JSON.stringify(schema));
46
- }
47
- /**
48
- * 解码 Schema 记录
49
- * @param value 记录值
50
- */
51
- export function decodeSchema(value) {
52
- let parsed;
53
- try {
54
- parsed = JSON.parse(BinaryUtils.decode(value));
55
- }
56
- catch (error) {
57
- throw new LightDbError(LightDbErrorCodes.corrupt, 'persisted schema record is not valid JSON', {
58
- operation: 'schema',
59
- cause: error,
60
- });
61
- }
62
- if (!isSchemaVersion(parsed)) {
63
- throw new LightDbError(LightDbErrorCodes.corrupt, 'persisted schema record has an unexpected shape', {
64
- operation: 'schema',
65
- });
66
- }
67
- return parsed;
68
- }
69
- /**
70
- * 判断值是否为 Schema 记录
71
- * @param value 待判断值
72
- */
73
- function isSchemaVersion(value) {
74
- if (typeof value !== 'object' || value === null) {
75
- return false;
76
- }
77
- const record = value;
78
- return typeof record.version === 'number' && typeof record.document === 'string';
79
- }
80
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/api/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG5D,yBAAyB;AACzB,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAE5C,mBAAmB;AACnB,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAE/C,aAAa;AACb,MAAM,cAAc,GAAG,+CAA+C,CAAC;AAEvE;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC5C,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,CAAC,CAAC;IACb,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAChD,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,YAAY,CAAC,iBAAiB,CAAC,aAAa,EAAE,mCAAmC,EAAE;YACzF,SAAS,EAAE,cAAc;SAC5B,CAAC,CAAC;IACP,CAAC;IACD,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAqB;IAC9C,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC1C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,YAAY,CAAC,iBAAiB,CAAC,OAAO,EAAE,2CAA2C,EAAE;YAC3F,SAAS,EAAE,QAAQ;YACnB,KAAK,EAAE,KAAK;SACf,CAAC,CAAC;IACP,CAAC;IAED,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,YAAY,CAAC,iBAAiB,CAAC,OAAO,EAAE,iDAAiD,EAAE;YACjG,SAAS,EAAE,QAAQ;SACtB,CAAC,CAAC;IACP,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,MAAM,GAAG,KAAkD,CAAC;IAClE,OAAO,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACrF,CAAC"}
@@ -1,26 +0,0 @@
1
- /**
2
- * 事务作者面
3
- *
4
- * 事务语义由 `core/engine` 维护,本层只提供异步调用形态与状态跟踪。
5
- */
6
- import type { StorageEngine } from '../core/engine';
7
- export type { TransactionState } from '../core/engine';
8
- /**
9
- * 事务句柄
10
- *
11
- * 一个数据库同时只允许一个写事务;重复开始会得到 `yydb.unsupported`。
12
- */
13
- export declare class Transaction {
14
- private readonly engine;
15
- private active;
16
- constructor(engine: StorageEngine);
17
- /** 是否处于事务中 */
18
- get isActive(): boolean;
19
- /** 开始事务 */
20
- begin(): Promise<void>;
21
- /** 提交事务,失败时事务仍视为结束 */
22
- commit(): Promise<void>;
23
- /** 回滚事务 */
24
- rollback(): Promise<void>;
25
- }
26
- //# sourceMappingURL=transaction.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/api/transaction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;GAIG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,EAAE,aAAa;IAIjC,cAAc;IACd,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,WAAW;IACE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKnC,sBAAsB;IACT,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAYpC,WAAW;IACE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAWzC"}
@@ -1,52 +0,0 @@
1
- /**
2
- * 事务作者面
3
- *
4
- * 事务语义由 `core/engine` 维护,本层只提供异步调用形态与状态跟踪。
5
- */
6
- import { LightDbError, LightDbErrorCodes } from '../errors';
7
- /**
8
- * 事务句柄
9
- *
10
- * 一个数据库同时只允许一个写事务;重复开始会得到 `yydb.unsupported`。
11
- */
12
- export class Transaction {
13
- engine;
14
- active = false;
15
- constructor(engine) {
16
- this.engine = engine;
17
- }
18
- /** 是否处于事务中 */
19
- get isActive() {
20
- return this.active;
21
- }
22
- /** 开始事务 */
23
- async begin() {
24
- this.engine.begin();
25
- this.active = true;
26
- }
27
- /** 提交事务,失败时事务仍视为结束 */
28
- async commit() {
29
- if (!this.active) {
30
- throw new LightDbError(LightDbErrorCodes.unsupported, 'no active transaction', { operation: 'commit' });
31
- }
32
- try {
33
- await this.engine.commit();
34
- }
35
- finally {
36
- this.active = false;
37
- }
38
- }
39
- /** 回滚事务 */
40
- async rollback() {
41
- if (!this.active) {
42
- throw new LightDbError(LightDbErrorCodes.unsupported, 'no active transaction', { operation: 'rollback' });
43
- }
44
- try {
45
- this.engine.rollback();
46
- }
47
- finally {
48
- this.active = false;
49
- }
50
- }
51
- }
52
- //# sourceMappingURL=transaction.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/api/transaction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAI5D;;;;GAIG;AACH,MAAM,OAAO,WAAW;IACH,MAAM,CAAgB;IAC/B,MAAM,GAAY,KAAK,CAAC;IAEhC,YAAY,MAAqB;QAC7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED,cAAc;IACd,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,WAAW;IACJ,KAAK,CAAC,KAAK;QACd,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,sBAAsB;IACf,KAAK,CAAC,MAAM;QACf,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,MAAM,IAAI,YAAY,CAAC,iBAAiB,CAAC,WAAW,EAAE,uBAAuB,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5G,CAAC;QAED,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/B,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACxB,CAAC;IACL,CAAC;IAED,WAAW;IACJ,KAAK,CAAC,QAAQ;QACjB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,MAAM,IAAI,YAAY,CAAC,iBAAiB,CAAC,WAAW,EAAE,uBAAuB,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9G,CAAC;QAED,IAAI,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACxB,CAAC;IACL,CAAC;CACJ"}
@@ -1,196 +0,0 @@
1
- /**
2
- * 浏览器原生二进制编解码
3
- *
4
- * 公共类型只用 `Uint8Array`,不依赖 Node `Buffer`。
5
- */
6
- /**
7
- * 二进制辅助方法
8
- */
9
- export declare class BinaryUtils {
10
- /**
11
- * 分配初始化为零的字节数组
12
- * @param size 大小
13
- */
14
- static alloc(size: number): Uint8Array;
15
- /**
16
- * 拼接多个字节数组
17
- * @param parts 字节数组列表
18
- */
19
- static concat(parts: readonly Uint8Array[]): Uint8Array;
20
- /**
21
- * 计算字符串的 UTF-8 字节长度
22
- * @param value 字符串
23
- */
24
- static byteLength(value: string): number;
25
- /**
26
- * 编码字符串为 UTF-8 字节
27
- * @param value 字符串
28
- */
29
- static encode(value: string): Uint8Array;
30
- /**
31
- * 解码 UTF-8 字节为字符串
32
- * @param data 字节
33
- * @param offset 起始偏移量
34
- * @param length 长度
35
- */
36
- static decode(data: Uint8Array, offset?: number, length?: number): string;
37
- /**
38
- * 判断两个字节数组内容是否相同
39
- * @param a 第一个数组
40
- * @param b 第二个数组
41
- */
42
- static equals(a: Uint8Array, b: Uint8Array): boolean;
43
- /**
44
- * 复制字节数组
45
- * @param source 源数组
46
- */
47
- static copy(source: Uint8Array): Uint8Array;
48
- }
49
- /**
50
- * 顺序字节写入器
51
- *
52
- * 容量不足时自动扩展,写入 `data` 时返回已写区间视图。
53
- */
54
- export declare class ByteWriter {
55
- private buffer;
56
- private view;
57
- private offset;
58
- /**
59
- * 创建写入器
60
- * @param size 初始容量
61
- */
62
- constructor(size?: number);
63
- /** 当前写入位置 */
64
- get position(): number;
65
- /** 已写入的数据视图 */
66
- get data(): Uint8Array;
67
- /**
68
- * 确保容量
69
- * @param additional 需要的额外字节数
70
- */
71
- private ensureCapacity;
72
- /**
73
- * 写入 8 位无符号整数
74
- * @param value 值
75
- */
76
- writeUInt8(value: number): this;
77
- /**
78
- * 写入 16 位无符号整数(小端)
79
- * @param value 值
80
- */
81
- writeUInt16LE(value: number): this;
82
- /**
83
- * 写入 32 位无符号整数(小端)
84
- * @param value 值
85
- */
86
- writeUInt32LE(value: number): this;
87
- /**
88
- * 写入 64 位无符号整数(小端)
89
- * @param value 值
90
- */
91
- writeBigUInt64LE(value: bigint): this;
92
- /**
93
- * 写入原始字节
94
- * @param value 字节
95
- */
96
- writeBytes(value: Uint8Array): this;
97
- /**
98
- * 写入带 32 位长度前缀的字节
99
- * @param value 字节
100
- */
101
- writeBytesWithLength(value: Uint8Array): this;
102
- /**
103
- * 写入不带长度前缀的 UTF-8 字符串
104
- * @param value 字符串
105
- */
106
- writeStringRaw(value: string): this;
107
- /**
108
- * 写入带 32 位长度前缀的 UTF-8 字符串
109
- * @param value 字符串
110
- */
111
- writeString(value: string): this;
112
- /**
113
- * 写入从 `startOffset` 到当前位置的 CRC32 校验和
114
- * @param startOffset 校验范围起点
115
- */
116
- writeChecksum(startOffset?: number): this;
117
- }
118
- /**
119
- * 顺序字节读取器
120
- */
121
- export declare class ByteReader {
122
- private readonly buffer;
123
- private readonly view;
124
- private offset;
125
- /**
126
- * 创建读取器
127
- * @param buffer 数据
128
- * @param startOffset 起始偏移量
129
- */
130
- constructor(buffer: Uint8Array, startOffset?: number);
131
- /** 当前读取位置 */
132
- get position(): number;
133
- /** 设置读取位置 */
134
- set position(value: number);
135
- /** 剩余可读字节数 */
136
- get remaining(): number;
137
- /**
138
- * 是否有足够的可读数据
139
- * @param required 需要的字节数
140
- */
141
- hasRemaining(required: number): boolean;
142
- /**
143
- * 读取 8 位无符号整数
144
- */
145
- readUInt8(): number;
146
- /**
147
- * 读取 16 位无符号整数(小端)
148
- */
149
- readUInt16LE(): number;
150
- /**
151
- * 读取 32 位无符号整数(小端)
152
- */
153
- readUInt32LE(): number;
154
- /**
155
- * 读取 64 位无符号整数(小端)
156
- */
157
- readBigUInt64LE(): bigint;
158
- /**
159
- * 读取指定长度的字节视图
160
- * @param length 长度
161
- */
162
- readBytes(length: number): Uint8Array;
163
- /**
164
- * 读取带 32 位长度前缀的字节
165
- */
166
- readBytesWithLength(): Uint8Array;
167
- /**
168
- * 读取带 32 位长度前缀的 UTF-8 字符串
169
- */
170
- readString(): string;
171
- /**
172
- * 读取 32 位校验和并校验 `[startOffset, 校验和之前)` 的区间
173
- * @param startOffset 校验范围起点
174
- */
175
- readAndVerifyChecksum(startOffset: number): number;
176
- /**
177
- * 跳过指定字节数
178
- * @param bytes 字节数
179
- */
180
- skip(bytes: number): this;
181
- }
182
- /**
183
- * 校验和不匹配
184
- *
185
- * codec 层不依赖具体错误模型,由上层转换成稳定错误码。
186
- */
187
- export declare class ChecksumMismatchError extends Error {
188
- /** 期望的校验和 */
189
- readonly expected: number;
190
- /** 实际计算出的校验和 */
191
- readonly actual: number;
192
- /** 校验区间起点 */
193
- readonly position: number;
194
- constructor(expected: number, actual: number, position: number);
195
- }
196
- //# sourceMappingURL=binary.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"binary.d.ts","sourceRoot":"","sources":["../../src/codec/binary.ts"],"names":[],"mappings":"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"}