@ocap/statedb 1.28.9 → 1.29.0

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.
package/README.md CHANGED
@@ -15,7 +15,7 @@ bun install @ocap/statedb-memory
15
15
  Then:
16
16
 
17
17
  ```javascript
18
- const MemoryStateDB = require('@ocap/statedb-memory');
18
+ const MemoryStateDB = require('@ocap/statedb-memory').default;
19
19
 
20
20
  const statedb = new MemoryStateDB();
21
21
 
package/esm/db.d.mts ADDED
@@ -0,0 +1,28 @@
1
+ import { Ready } from "@ocap/util/lib/ready";
2
+
3
+ //#region src/db.d.ts
4
+
5
+ /**
6
+ * StateDB 基类
7
+ * 提供状态数据库的基础功能,子类需要实现具体的表
8
+ */
9
+ declare class StateDB extends Ready {
10
+ /** 数据库名称 */
11
+ name: string;
12
+ /** 数据库版本 */
13
+ version?: string;
14
+ /** 所有表名列表 */
15
+ tables: readonly string[];
16
+ /** 表就绪标记 */
17
+ readyMarks: Record<string, boolean>;
18
+ /** 是否已附加就绪监听器 */
19
+ readyListenersAttached: boolean;
20
+ constructor();
21
+ /**
22
+ * 附加表就绪监听器
23
+ * 当所有表都就绪时,StateDB 才会标记为就绪
24
+ */
25
+ attachReadyListeners(): void;
26
+ }
27
+ //#endregion
28
+ export { StateDB as default };
package/esm/db.mjs ADDED
@@ -0,0 +1,32 @@
1
+ import { tables } from "@ocap/state";
2
+ import { Ready } from "@ocap/util/lib/ready";
3
+
4
+ //#region src/db.ts
5
+ /**
6
+ * StateDB 基类
7
+ * 提供状态数据库的基础功能,子类需要实现具体的表
8
+ */
9
+ var StateDB = class extends Ready {
10
+ constructor() {
11
+ super();
12
+ this.tables = tables;
13
+ this.readyMarks = Object.fromEntries(tables.map((x) => [x, false]));
14
+ this.readyListenersAttached = false;
15
+ }
16
+ /**
17
+ * 附加表就绪监听器
18
+ * 当所有表都就绪时,StateDB 才会标记为就绪
19
+ */
20
+ attachReadyListeners() {
21
+ if (this.readyListenersAttached) return;
22
+ for (const table of tables) {
23
+ if (typeof this[table] === "undefined") throw new Error(`Missing table ${table} in statedb adapter: ${this.name}`);
24
+ this[table].onReady(() => this.markReady(table));
25
+ }
26
+ this.readyListenersAttached = true;
27
+ }
28
+ };
29
+ var db_default = StateDB;
30
+
31
+ //#endregion
32
+ export { db_default as default };
@@ -0,0 +1,3 @@
1
+ import StateDB from "./db.mjs";
2
+ import StateDBTable from "./table.mjs";
3
+ export { StateDB, StateDBTable };
package/esm/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import db_default from "./db.mjs";
2
+ import table_default from "./table.mjs";
3
+
4
+ export { db_default as StateDB, table_default as StateDBTable };
@@ -0,0 +1,38 @@
1
+ import { Ready } from "@ocap/util/lib/ready";
2
+ import { HookFunction, IOperationContext, IStateTable } from "@ocap/types";
3
+
4
+ //#region src/table.d.ts
5
+
6
+ /**
7
+ * StateDB 表基类
8
+ * 实现 IStateTable 接口,提供状态管理的基础功能
9
+ */
10
+ declare class StateDBTable<T = unknown> extends Ready implements IStateTable<T> {
11
+ uniqIndex: string | string[] | undefined;
12
+ primaryKey: string;
13
+ name: string;
14
+ constructor(uniqIndex?: string | string[]);
15
+ pre: (name: string, fn: HookFunction) => void;
16
+ post: (name: string, fn: HookFunction) => void;
17
+ create: (id: string, attrs: Partial<T>, context?: IOperationContext) => Promise<T>;
18
+ get: (id: string, context?: IOperationContext) => Promise<T | null>;
19
+ update: (id: string, updates: Partial<T>, context?: IOperationContext) => Promise<T>;
20
+ history: (id: string, context?: IOperationContext) => Promise<T[]>;
21
+ reset: (context?: IOperationContext) => Promise<void>;
22
+ _create(_id: string, _attrs: Partial<T>, _context?: IOperationContext): Promise<T> | T;
23
+ _get(_id: string, _context?: IOperationContext): Promise<T | null> | T | null;
24
+ _update(_id: string, _updates: Partial<T>, _context?: IOperationContext): Promise<T> | T;
25
+ _reset(_context?: IOperationContext): Promise<void> | void;
26
+ _history(_id: string, _context?: IOperationContext): Promise<T[]> | T[];
27
+ updateOrCreate(_exist: unknown, _state: Partial<T>, _context?: IOperationContext): Promise<T> | T;
28
+ /**
29
+ * Generate an ID composed of multiple primary keys
30
+ */
31
+ generatePrimaryKey(doc: string | Record<string, unknown>): string;
32
+ /** update cache for context */
33
+ updateCache(data: Record<string, unknown>, context: IOperationContext | null | undefined): void;
34
+ /** get data from cache for context */
35
+ getCache(key: string | Record<string, unknown>, context: IOperationContext): T | null;
36
+ }
37
+ //#endregion
38
+ export { StateDBTable as default };
package/esm/table.mjs ADDED
@@ -0,0 +1,117 @@
1
+ import { Ready } from "@ocap/util/lib/ready";
2
+ import crypto from "node:crypto";
3
+ import { isValid } from "@arcblock/did";
4
+ import { toAddress } from "@ocap/util";
5
+ import Kareem from "kareem";
6
+ import omit from "lodash/omit.js";
7
+ import pick from "lodash/pick.js";
8
+
9
+ //#region src/table.ts
10
+ /**
11
+ * StateDB 表基类
12
+ * 实现 IStateTable 接口,提供状态管理的基础功能
13
+ */
14
+ var StateDBTable = class extends Ready {
15
+ constructor(uniqIndex) {
16
+ super();
17
+ this.name = "";
18
+ this.uniqIndex = uniqIndex;
19
+ this.primaryKey = typeof uniqIndex === "string" ? uniqIndex : "id";
20
+ const hooks = new Kareem();
21
+ Object.defineProperty(this, "pre", { value: (name, fn) => hooks.pre(name, fn) });
22
+ Object.defineProperty(this, "post", { value: (name, fn) => hooks.post(name, fn) });
23
+ [
24
+ "create",
25
+ "get",
26
+ "history",
27
+ "update",
28
+ "reset"
29
+ ].forEach((x) => {
30
+ Object.defineProperty(this, x, { value: async (...args) => {
31
+ if (typeof args[0] === "string" && isValid(args[0])) args[0] = toAddress(args[0]);
32
+ hooks.execPreSync(x, args);
33
+ const result = await this[`_${x}`](...args);
34
+ hooks.execPostSync(x, result);
35
+ if ([
36
+ "create",
37
+ "update",
38
+ "reset"
39
+ ].includes(x)) {
40
+ const ctx = args.slice(-1).pop();
41
+ if (ctx?.tx) {
42
+ const events = ctx.events || [];
43
+ events.push({
44
+ table: this.name,
45
+ name: x,
46
+ data: omit(result, "$loki"),
47
+ ctx: pick(ctx, Object.keys(ctx).filter((k) => [
48
+ "events",
49
+ "states",
50
+ "statedb"
51
+ ].includes(k) === false))
52
+ });
53
+ ctx.events = events;
54
+ }
55
+ }
56
+ if (result) {
57
+ if (!result._retrievedAt) Object.defineProperty(result, "_retrievedAt", {
58
+ value: process.hrtime.bigint(),
59
+ enumerable: false,
60
+ writable: true,
61
+ configurable: true
62
+ });
63
+ else if (["create", "update"].includes(x)) result._retrievedAt = process.hrtime.bigint();
64
+ }
65
+ return result;
66
+ } });
67
+ });
68
+ }
69
+ _create(_id, _attrs, _context) {
70
+ throw new Error("`_create` must be implemented in sub statedb");
71
+ }
72
+ _get(_id, _context) {
73
+ throw new Error("`_get` must be implemented in sub statedb");
74
+ }
75
+ _update(_id, _updates, _context) {
76
+ throw new Error("`_update` must be implemented in sub statedb");
77
+ }
78
+ _reset(_context) {
79
+ throw new Error("`_reset` must be implemented in sub statedb");
80
+ }
81
+ _history(_id, _context) {
82
+ throw new Error("`_history` must be implemented in sub statedb");
83
+ }
84
+ updateOrCreate(_exist, _state, _context) {
85
+ throw new Error("`updateOrCreate` must be implemented in sub statedb");
86
+ }
87
+ /**
88
+ * Generate an ID composed of multiple primary keys
89
+ */
90
+ generatePrimaryKey(doc) {
91
+ if (typeof doc === "string") return doc;
92
+ if (Array.isArray(this.uniqIndex)) {
93
+ const key = this.uniqIndex.map((id) => doc[id]).map((item) => typeof item === "object" ? JSON.stringify(item) : item).join("-");
94
+ return crypto.createHash("md5").update(key).digest("hex");
95
+ }
96
+ return doc[this.uniqIndex];
97
+ }
98
+ /** update cache for context */
99
+ updateCache(data, context) {
100
+ if (!context) return;
101
+ const cacheStates = context.cacheStates || {};
102
+ if (!cacheStates[this.name]) cacheStates[this.name] = {};
103
+ const cacheKey = this.generatePrimaryKey(data);
104
+ cacheStates[this.name][cacheKey] = data;
105
+ context.cacheStates = cacheStates;
106
+ }
107
+ /** get data from cache for context */
108
+ getCache(key, context) {
109
+ const cacheStates = context.cacheStates || {};
110
+ const cacheKey = this.generatePrimaryKey(key);
111
+ return cacheStates[this.name]?.[cacheKey] || null;
112
+ }
113
+ };
114
+ var table_default = StateDBTable;
115
+
116
+ //#endregion
117
+ export { table_default as default };
@@ -0,0 +1,29 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+
29
+ exports.__toESM = __toESM;
package/lib/db.cjs ADDED
@@ -0,0 +1,34 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
3
+ let _ocap_state = require("@ocap/state");
4
+ let _ocap_util_lib_ready = require("@ocap/util/lib/ready");
5
+
6
+ //#region src/db.ts
7
+ /**
8
+ * StateDB 基类
9
+ * 提供状态数据库的基础功能,子类需要实现具体的表
10
+ */
11
+ var StateDB = class extends _ocap_util_lib_ready.Ready {
12
+ constructor() {
13
+ super();
14
+ this.tables = _ocap_state.tables;
15
+ this.readyMarks = Object.fromEntries(_ocap_state.tables.map((x) => [x, false]));
16
+ this.readyListenersAttached = false;
17
+ }
18
+ /**
19
+ * 附加表就绪监听器
20
+ * 当所有表都就绪时,StateDB 才会标记为就绪
21
+ */
22
+ attachReadyListeners() {
23
+ if (this.readyListenersAttached) return;
24
+ for (const table of _ocap_state.tables) {
25
+ if (typeof this[table] === "undefined") throw new Error(`Missing table ${table} in statedb adapter: ${this.name}`);
26
+ this[table].onReady(() => this.markReady(table));
27
+ }
28
+ this.readyListenersAttached = true;
29
+ }
30
+ };
31
+ var db_default = StateDB;
32
+
33
+ //#endregion
34
+ exports.default = db_default;
package/lib/db.d.cts ADDED
@@ -0,0 +1,28 @@
1
+ import { Ready } from "@ocap/util/lib/ready";
2
+
3
+ //#region src/db.d.ts
4
+
5
+ /**
6
+ * StateDB 基类
7
+ * 提供状态数据库的基础功能,子类需要实现具体的表
8
+ */
9
+ declare class StateDB extends Ready {
10
+ /** 数据库名称 */
11
+ name: string;
12
+ /** 数据库版本 */
13
+ version?: string;
14
+ /** 所有表名列表 */
15
+ tables: readonly string[];
16
+ /** 表就绪标记 */
17
+ readyMarks: Record<string, boolean>;
18
+ /** 是否已附加就绪监听器 */
19
+ readyListenersAttached: boolean;
20
+ constructor();
21
+ /**
22
+ * 附加表就绪监听器
23
+ * 当所有表都就绪时,StateDB 才会标记为就绪
24
+ */
25
+ attachReadyListeners(): void;
26
+ }
27
+ //#endregion
28
+ export { StateDB as default };
package/lib/index.cjs ADDED
@@ -0,0 +1,5 @@
1
+ const require_db = require('./db.cjs');
2
+ const require_table = require('./table.cjs');
3
+
4
+ exports.StateDB = require_db.default;
5
+ exports.StateDBTable = require_table.default;
@@ -0,0 +1,3 @@
1
+ import StateDB from "./db.cjs";
2
+ import StateDBTable from "./table.cjs";
3
+ export { StateDB, StateDBTable };
package/lib/table.cjs ADDED
@@ -0,0 +1,123 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
3
+ let _ocap_util_lib_ready = require("@ocap/util/lib/ready");
4
+ let node_crypto = require("node:crypto");
5
+ node_crypto = require_rolldown_runtime.__toESM(node_crypto);
6
+ let _arcblock_did = require("@arcblock/did");
7
+ let _ocap_util = require("@ocap/util");
8
+ let kareem = require("kareem");
9
+ kareem = require_rolldown_runtime.__toESM(kareem);
10
+ let lodash_omit = require("lodash/omit");
11
+ lodash_omit = require_rolldown_runtime.__toESM(lodash_omit);
12
+ let lodash_pick = require("lodash/pick");
13
+ lodash_pick = require_rolldown_runtime.__toESM(lodash_pick);
14
+
15
+ //#region src/table.ts
16
+ /**
17
+ * StateDB 表基类
18
+ * 实现 IStateTable 接口,提供状态管理的基础功能
19
+ */
20
+ var StateDBTable = class extends _ocap_util_lib_ready.Ready {
21
+ constructor(uniqIndex) {
22
+ super();
23
+ this.name = "";
24
+ this.uniqIndex = uniqIndex;
25
+ this.primaryKey = typeof uniqIndex === "string" ? uniqIndex : "id";
26
+ const hooks = new kareem.default();
27
+ Object.defineProperty(this, "pre", { value: (name, fn) => hooks.pre(name, fn) });
28
+ Object.defineProperty(this, "post", { value: (name, fn) => hooks.post(name, fn) });
29
+ [
30
+ "create",
31
+ "get",
32
+ "history",
33
+ "update",
34
+ "reset"
35
+ ].forEach((x) => {
36
+ Object.defineProperty(this, x, { value: async (...args) => {
37
+ if (typeof args[0] === "string" && (0, _arcblock_did.isValid)(args[0])) args[0] = (0, _ocap_util.toAddress)(args[0]);
38
+ hooks.execPreSync(x, args);
39
+ const result = await this[`_${x}`](...args);
40
+ hooks.execPostSync(x, result);
41
+ if ([
42
+ "create",
43
+ "update",
44
+ "reset"
45
+ ].includes(x)) {
46
+ const ctx = args.slice(-1).pop();
47
+ if (ctx?.tx) {
48
+ const events = ctx.events || [];
49
+ events.push({
50
+ table: this.name,
51
+ name: x,
52
+ data: (0, lodash_omit.default)(result, "$loki"),
53
+ ctx: (0, lodash_pick.default)(ctx, Object.keys(ctx).filter((k) => [
54
+ "events",
55
+ "states",
56
+ "statedb"
57
+ ].includes(k) === false))
58
+ });
59
+ ctx.events = events;
60
+ }
61
+ }
62
+ if (result) {
63
+ if (!result._retrievedAt) Object.defineProperty(result, "_retrievedAt", {
64
+ value: process.hrtime.bigint(),
65
+ enumerable: false,
66
+ writable: true,
67
+ configurable: true
68
+ });
69
+ else if (["create", "update"].includes(x)) result._retrievedAt = process.hrtime.bigint();
70
+ }
71
+ return result;
72
+ } });
73
+ });
74
+ }
75
+ _create(_id, _attrs, _context) {
76
+ throw new Error("`_create` must be implemented in sub statedb");
77
+ }
78
+ _get(_id, _context) {
79
+ throw new Error("`_get` must be implemented in sub statedb");
80
+ }
81
+ _update(_id, _updates, _context) {
82
+ throw new Error("`_update` must be implemented in sub statedb");
83
+ }
84
+ _reset(_context) {
85
+ throw new Error("`_reset` must be implemented in sub statedb");
86
+ }
87
+ _history(_id, _context) {
88
+ throw new Error("`_history` must be implemented in sub statedb");
89
+ }
90
+ updateOrCreate(_exist, _state, _context) {
91
+ throw new Error("`updateOrCreate` must be implemented in sub statedb");
92
+ }
93
+ /**
94
+ * Generate an ID composed of multiple primary keys
95
+ */
96
+ generatePrimaryKey(doc) {
97
+ if (typeof doc === "string") return doc;
98
+ if (Array.isArray(this.uniqIndex)) {
99
+ const key = this.uniqIndex.map((id) => doc[id]).map((item) => typeof item === "object" ? JSON.stringify(item) : item).join("-");
100
+ return node_crypto.default.createHash("md5").update(key).digest("hex");
101
+ }
102
+ return doc[this.uniqIndex];
103
+ }
104
+ /** update cache for context */
105
+ updateCache(data, context) {
106
+ if (!context) return;
107
+ const cacheStates = context.cacheStates || {};
108
+ if (!cacheStates[this.name]) cacheStates[this.name] = {};
109
+ const cacheKey = this.generatePrimaryKey(data);
110
+ cacheStates[this.name][cacheKey] = data;
111
+ context.cacheStates = cacheStates;
112
+ }
113
+ /** get data from cache for context */
114
+ getCache(key, context) {
115
+ const cacheStates = context.cacheStates || {};
116
+ const cacheKey = this.generatePrimaryKey(key);
117
+ return cacheStates[this.name]?.[cacheKey] || null;
118
+ }
119
+ };
120
+ var table_default = StateDBTable;
121
+
122
+ //#endregion
123
+ exports.default = table_default;
@@ -0,0 +1,38 @@
1
+ import { Ready } from "@ocap/util/lib/ready";
2
+ import { HookFunction, IOperationContext, IStateTable } from "@ocap/types";
3
+
4
+ //#region src/table.d.ts
5
+
6
+ /**
7
+ * StateDB 表基类
8
+ * 实现 IStateTable 接口,提供状态管理的基础功能
9
+ */
10
+ declare class StateDBTable<T = unknown> extends Ready implements IStateTable<T> {
11
+ uniqIndex: string | string[] | undefined;
12
+ primaryKey: string;
13
+ name: string;
14
+ constructor(uniqIndex?: string | string[]);
15
+ pre: (name: string, fn: HookFunction) => void;
16
+ post: (name: string, fn: HookFunction) => void;
17
+ create: (id: string, attrs: Partial<T>, context?: IOperationContext) => Promise<T>;
18
+ get: (id: string, context?: IOperationContext) => Promise<T | null>;
19
+ update: (id: string, updates: Partial<T>, context?: IOperationContext) => Promise<T>;
20
+ history: (id: string, context?: IOperationContext) => Promise<T[]>;
21
+ reset: (context?: IOperationContext) => Promise<void>;
22
+ _create(_id: string, _attrs: Partial<T>, _context?: IOperationContext): Promise<T> | T;
23
+ _get(_id: string, _context?: IOperationContext): Promise<T | null> | T | null;
24
+ _update(_id: string, _updates: Partial<T>, _context?: IOperationContext): Promise<T> | T;
25
+ _reset(_context?: IOperationContext): Promise<void> | void;
26
+ _history(_id: string, _context?: IOperationContext): Promise<T[]> | T[];
27
+ updateOrCreate(_exist: unknown, _state: Partial<T>, _context?: IOperationContext): Promise<T> | T;
28
+ /**
29
+ * Generate an ID composed of multiple primary keys
30
+ */
31
+ generatePrimaryKey(doc: string | Record<string, unknown>): string;
32
+ /** update cache for context */
33
+ updateCache(data: Record<string, unknown>, context: IOperationContext | null | undefined): void;
34
+ /** get data from cache for context */
35
+ getCache(key: string | Record<string, unknown>, context: IOperationContext): T | null;
36
+ }
37
+ //#endregion
38
+ export { StateDBTable as default };
package/package.json CHANGED
@@ -3,13 +3,36 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.28.9",
6
+ "version": "1.29.0",
7
7
  "description": "Defines the basic interface for OCAP StateDB",
8
- "main": "lib/index.js",
8
+ "type": "module",
9
+ "main": "./lib/index.cjs",
10
+ "module": "./esm/index.mjs",
11
+ "types": "./esm/index.d.mts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./esm/index.d.mts",
15
+ "import": "./esm/index.mjs",
16
+ "default": "./lib/index.cjs"
17
+ },
18
+ "./lib/*.js": {
19
+ "types": "./esm/*.d.mts",
20
+ "import": "./esm/*.mjs",
21
+ "default": "./lib/*.cjs"
22
+ },
23
+ "./lib/*": {
24
+ "types": "./esm/*.d.mts",
25
+ "import": "./esm/*.mjs",
26
+ "default": "./lib/*.cjs"
27
+ }
28
+ },
9
29
  "files": [
10
- "lib"
30
+ "lib",
31
+ "esm"
11
32
  ],
12
33
  "scripts": {
34
+ "build": "tsdown",
35
+ "prebuild": "rm -rf lib esm",
13
36
  "lint": "biome check",
14
37
  "lint:fix": "biome check --write",
15
38
  "test": "bun test",
@@ -20,10 +43,11 @@
20
43
  "license": "MIT",
21
44
  "devDependencies": {},
22
45
  "dependencies": {
23
- "@arcblock/did": "1.28.9",
24
- "@ocap/state": "1.28.9",
25
- "@ocap/util": "1.28.9",
46
+ "@arcblock/did": "1.29.0",
47
+ "@ocap/state": "1.29.0",
48
+ "@ocap/types": "1.29.0",
49
+ "@ocap/util": "1.29.0",
26
50
  "kareem": "^2.4.1",
27
- "lodash": "^4.17.21"
51
+ "lodash": "^4.17.23"
28
52
  }
29
53
  }
package/lib/db.d.ts DELETED
@@ -1,19 +0,0 @@
1
- // Generate by [js2dts@0.3.3](https://github.com/whxaxes/js2dts#readme)
2
-
3
- declare class Ready {
4
- emit: any;
5
- ready: any;
6
- readyCallbacks: any;
7
- readyMarks: any;
8
- constructor();
9
- markReady(mark?: any): void;
10
- onReady(cb: any): void;
11
- }
12
- declare class StateDB extends Ready {
13
- readyMarks: any;
14
- readyListenersAttached: boolean;
15
- constructor();
16
- attachReadyListeners(): void;
17
- }
18
- declare const _Db: typeof StateDB;
19
- export = _Db;
package/lib/db.js DELETED
@@ -1,30 +0,0 @@
1
- const { Ready } = require('@ocap/util/lib/ready');
2
- const { tables } = require('@ocap/state');
3
-
4
- class StateDB extends Ready {
5
- constructor() {
6
- super();
7
-
8
- this.tables = tables;
9
- this.readyMarks = Object.fromEntries(tables.map((x) => [x, false]));
10
- this.readyListenersAttached = false;
11
- }
12
-
13
- attachReadyListeners() {
14
- if (this.readyListenersAttached) {
15
- return;
16
- }
17
-
18
- for (const table of tables) {
19
- if (typeof this[table] === 'undefined') {
20
- throw new Error(`Missing table ${table} in statedb adapter: ${this.name}`);
21
- }
22
-
23
- this[table].onReady(() => this.markReady(table));
24
- }
25
-
26
- this.readyListenersAttached = true;
27
- }
28
- }
29
-
30
- module.exports = StateDB;
package/lib/index.js DELETED
@@ -1,4 +0,0 @@
1
- const StateDBTable = require('./table');
2
- const StateDB = require('./db');
3
-
4
- module.exports = { StateDB, StateDBTable };
package/lib/table.d.ts DELETED
@@ -1,27 +0,0 @@
1
- type Promisable<T> = T | Promise<T>;
2
-
3
- declare class Ready {
4
- emit: any;
5
- ready: any;
6
- readyCallbacks: any;
7
- readyMarks: any;
8
- constructor();
9
- markReady(mark?: any): void;
10
- onReady(cb: any): void;
11
- }
12
- declare class StateDBTable extends Ready {
13
- protected _create(id: string, attrs: any, context?: any): Promisable<any>;
14
- protected _get(id: string, context?: any): Promisable<any>;
15
- protected _update(id: string, updates: any, context?: any): Promisable<any>;
16
- protected _history(id: string, context?: any): Promisable<any>;
17
- protected _reset(context?: any): Promisable<void>;
18
-
19
- public create(id: string, attrs: any, context?: any): Promisable<any>;
20
- public get(id: string, context?: any): Promisable<any>;
21
- public update(id: string, updates: any, context?: any): Promisable<any>;
22
- public history(id: string, context?: any): Promisable<any>;
23
- public updateOrCreate(id: string, attrs: any, context?: any): Promisable<any>;
24
- public reset(context?: any): Promisable<void>;
25
- }
26
- declare const Table: typeof StateDBTable;
27
- export = Table;
package/lib/table.js DELETED
@@ -1,134 +0,0 @@
1
- const crypto = require('node:crypto');
2
- const Kareem = require('kareem');
3
- const omit = require('lodash/omit');
4
- const pick = require('lodash/pick');
5
- const { Ready } = require('@ocap/util/lib/ready');
6
- const { isValid } = require('@arcblock/did');
7
- const { toAddress } = require('@ocap/util');
8
-
9
- class StateDBTable extends Ready {
10
- constructor(uniqIndex) {
11
- super();
12
-
13
- this.uniqIndex = uniqIndex;
14
- this.primaryKey = typeof uniqIndex === 'string' ? uniqIndex : 'id';
15
-
16
- const hooks = new Kareem();
17
-
18
- Object.defineProperty(this, 'pre', { value: (name, fn) => hooks.pre(name, fn) });
19
- Object.defineProperty(this, 'post', { value: (name, fn) => hooks.post(name, fn) });
20
-
21
- ['create', 'get', 'history', 'update', 'reset'].forEach((x) => {
22
- Object.defineProperty(this, x, {
23
- value: async (...args) => {
24
- // Ensure the storage layer omits the `did:abt` prefix
25
- if (typeof args[0] === 'string' && isValid(args[0])) {
26
- args[0] = toAddress(args[0]);
27
- }
28
-
29
- hooks.execPreSync(x, args);
30
- const result = await this[`_${x}`](...args);
31
- hooks.execPostSync(x, result);
32
-
33
- if (['create', 'update', 'reset'].includes(x)) {
34
- const ctx = args.slice(-1).pop();
35
- if (ctx?.tx) {
36
- ctx.events = ctx.events || [];
37
- ctx.events.push({
38
- table: this.name,
39
- name: x,
40
- data: omit(result, '$loki'),
41
- ctx: pick(
42
- ctx,
43
- Object.keys(ctx).filter((k) => ['events', 'states', 'statedb'].includes(k) === false)
44
- ),
45
- });
46
- }
47
- }
48
-
49
- if (result) {
50
- if (!result._retrievedAt) {
51
- Object.defineProperty(result, '_retrievedAt', {
52
- value: process.hrtime.bigint(),
53
- enumerable: false,
54
- writable: true,
55
- configurable: true,
56
- });
57
- }
58
- // refresh the retrievedAt time for create and update
59
- else if (['create', 'update'].includes(x)) {
60
- result._retrievedAt = process.hrtime.bigint();
61
- }
62
- }
63
-
64
- return result;
65
- },
66
- });
67
- });
68
- }
69
-
70
- _create(_id, _attrs, _context) {
71
- throw new Error('`_create` must be implemented in sub statedb');
72
- }
73
-
74
- _get(_id, _context) {
75
- throw new Error('`_get` must be implemented in sub statedb');
76
- }
77
-
78
- _update(_id, _updates, _context) {
79
- throw new Error('`_update` must be implemented in sub statedb');
80
- }
81
-
82
- _reset(_context) {
83
- throw new Error('`_reset` must be implemented in sub statedb');
84
- }
85
-
86
- _history(_id, _context) {
87
- throw new Error('`_history` must be implemented in sub statedb');
88
- }
89
-
90
- updateOrCreate(_id, _attrs, _context) {
91
- throw new Error('`updateOrCreate` must be implemented in sub statedb');
92
- }
93
-
94
- /**
95
- * Generate an ID composed of multiple primary keys
96
- */
97
- generatePrimaryKey(doc) {
98
- if (typeof doc === 'string') {
99
- return doc;
100
- }
101
-
102
- // composite primary key
103
- if (Array.isArray(this.uniqIndex)) {
104
- const key = this.uniqIndex
105
- .map((id) => doc[id])
106
- .map((item) => (typeof item === 'object' ? JSON.stringify(item) : item))
107
- .join('-');
108
- return crypto.createHash('md5').update(key).digest('hex');
109
- }
110
-
111
- return doc[this.uniqIndex];
112
- }
113
-
114
- /** update cache for context */
115
- updateCache(data, context) {
116
- if (!context) return;
117
- if (!context.cacheStates?.[this.name]) {
118
- context.cacheStates = context.cacheStates || {};
119
- context.cacheStates[this.name] = {};
120
- }
121
-
122
- const cacheKey = this.generatePrimaryKey(data);
123
- context.cacheStates[this.name][cacheKey] = data;
124
- }
125
-
126
- /** get data from cache for context */
127
- getCache(key, context) {
128
- const cacheStates = context.cacheStates || {};
129
- const cacheKey = this.generatePrimaryKey(key);
130
- return cacheStates[this.name]?.[cacheKey] || null;
131
- }
132
- }
133
-
134
- module.exports = StateDBTable;