@ocap/statedb-sqlite 1.29.5

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 (50) hide show
  1. package/README.md +66 -0
  2. package/esm/_virtual/rolldown_runtime.mjs +21 -0
  3. package/esm/db.d.mts +92 -0
  4. package/esm/db.mjs +257 -0
  5. package/esm/index.d.mts +4 -0
  6. package/esm/index.mjs +7 -0
  7. package/esm/interfaces.d.mts +201 -0
  8. package/esm/interfaces.mjs +1 -0
  9. package/esm/kysely.d.mts +43 -0
  10. package/esm/kysely.mjs +62 -0
  11. package/esm/migrations/001-genesis.d.mts +14 -0
  12. package/esm/migrations/001-genesis.mjs +52 -0
  13. package/esm/migrations/index.d.mts +24 -0
  14. package/esm/migrations/index.mjs +60 -0
  15. package/esm/package.mjs +70 -0
  16. package/esm/table/account.d.mts +40 -0
  17. package/esm/table/account.mjs +99 -0
  18. package/esm/table/balance.d.mts +39 -0
  19. package/esm/table/balance.mjs +69 -0
  20. package/esm/table/base.d.mts +84 -0
  21. package/esm/table/base.mjs +217 -0
  22. package/esm/table/rollup.d.mts +22 -0
  23. package/esm/table/rollup.mjs +44 -0
  24. package/esm/table/token.d.mts +23 -0
  25. package/esm/table/token.mjs +42 -0
  26. package/lib/_virtual/rolldown_runtime.cjs +43 -0
  27. package/lib/db.cjs +259 -0
  28. package/lib/db.d.cts +92 -0
  29. package/lib/index.cjs +9 -0
  30. package/lib/index.d.cts +4 -0
  31. package/lib/interfaces.cjs +0 -0
  32. package/lib/interfaces.d.cts +201 -0
  33. package/lib/kysely.cjs +63 -0
  34. package/lib/kysely.d.cts +43 -0
  35. package/lib/migrations/001-genesis.cjs +59 -0
  36. package/lib/migrations/001-genesis.d.cts +14 -0
  37. package/lib/migrations/index.cjs +62 -0
  38. package/lib/migrations/index.d.cts +24 -0
  39. package/lib/package.cjs +76 -0
  40. package/lib/table/account.cjs +101 -0
  41. package/lib/table/account.d.cts +40 -0
  42. package/lib/table/balance.cjs +71 -0
  43. package/lib/table/balance.d.cts +39 -0
  44. package/lib/table/base.cjs +221 -0
  45. package/lib/table/base.d.cts +84 -0
  46. package/lib/table/rollup.cjs +45 -0
  47. package/lib/table/rollup.d.cts +22 -0
  48. package/lib/table/token.cjs +43 -0
  49. package/lib/table/token.d.cts +23 -0
  50. package/package.json +75 -0
@@ -0,0 +1,217 @@
1
+ import { StateDBTable } from "@ocap/statedb";
2
+ import crypto from "node:crypto";
3
+ import omit from "lodash/omit.js";
4
+
5
+ //#region src/table/base.ts
6
+ /**
7
+ * SQLite State Table base class
8
+ * Extends StateDBTable to provide SQLite-specific implementation
9
+ */
10
+ var SqliteTable = class SqliteTable extends StateDBTable {
11
+ constructor(config) {
12
+ super(config.uniqIndex);
13
+ this.name = config.name;
14
+ this.db = config.db;
15
+ this.schema = config.schema || {};
16
+ this.balanceTable = config.balanceTable;
17
+ this.syncBalance = config.syncBalance ?? false;
18
+ if (this.syncBalance && !this.balanceTable) throw new Error("balanceTable is required when syncBalance is true");
19
+ this.markReady();
20
+ }
21
+ /**
22
+ * Get the Kysely executor (use transaction if available)
23
+ */
24
+ getExecutor(context) {
25
+ return context?.txn || this.db;
26
+ }
27
+ /**
28
+ * Generate primary key from document
29
+ * Handles both simple string keys and composite keys
30
+ */
31
+ generatePrimaryKey(doc) {
32
+ if (typeof doc === "string") return doc;
33
+ if (Array.isArray(this.uniqIndex)) {
34
+ const key = this.uniqIndex.map((id) => doc[id]).map((item) => typeof item === "object" ? JSON.stringify(item) : item).join("-");
35
+ return crypto.createHash("md5").update(key).digest("hex");
36
+ }
37
+ return doc[this.uniqIndex];
38
+ }
39
+ /**
40
+ * Convert a key to a query object
41
+ */
42
+ formatKeyToQuery(key) {
43
+ if (Array.isArray(this.uniqIndex) && typeof key === "object") {
44
+ const keyObj = key;
45
+ return Object.fromEntries(this.uniqIndex.map((k) => [this.mapColumnName(k), keyObj[k]]));
46
+ }
47
+ if (typeof key === "object") {
48
+ const keyObj = key;
49
+ return { [this.mapColumnName(this.primaryKey)]: keyObj[this.primaryKey] };
50
+ }
51
+ return { [this.mapColumnName(this.primaryKey)]: key };
52
+ }
53
+ /**
54
+ * Map column name for reserved keywords
55
+ */
56
+ mapColumnName(name) {
57
+ return this.schema.columnMapping?.[name] ?? name;
58
+ }
59
+ /**
60
+ * Reverse map column name
61
+ */
62
+ unmapColumnName(name) {
63
+ const mapping = this.schema.columnMapping;
64
+ if (!mapping) return name;
65
+ for (const [original, mapped] of Object.entries(mapping)) if (mapped === name) return original;
66
+ return name;
67
+ }
68
+ /**
69
+ * Serialize data for database insert
70
+ * - Converts objects/arrays to JSON strings
71
+ * - Converts booleans to integers (0/1) for SQLite
72
+ * - Maps column names for reserved keywords
73
+ */
74
+ serializeForDb(data) {
75
+ const result = {};
76
+ const jsonFields = new Set(this.schema.jsonFields || []);
77
+ const booleanFields = new Set(this.schema.booleanFields || []);
78
+ for (const [key, value] of Object.entries(data)) {
79
+ const mappedKey = this.mapColumnName(key);
80
+ if (value === void 0) result[mappedKey] = null;
81
+ else if (booleanFields.has(key) && typeof value === "boolean") result[mappedKey] = value ? 1 : 0;
82
+ else if (jsonFields.has(key) || value !== null && typeof value === "object") result[mappedKey] = JSON.stringify(value);
83
+ else result[mappedKey] = value;
84
+ }
85
+ return result;
86
+ }
87
+ /**
88
+ * Deserialize data from database read
89
+ * - Parses JSON strings back to objects
90
+ * - Converts integers (0/1) back to booleans
91
+ * - Unmaps column names
92
+ */
93
+ deserializeFromDb(data) {
94
+ if (!data) return null;
95
+ const result = {};
96
+ const jsonFields = new Set(this.schema.jsonFields || []);
97
+ const booleanFields = new Set(this.schema.booleanFields || []);
98
+ for (const [key, value] of Object.entries(data)) {
99
+ const unmappedKey = this.unmapColumnName(key);
100
+ if (booleanFields.has(unmappedKey) && typeof value === "number") result[unmappedKey] = value === 1;
101
+ else if (jsonFields.has(unmappedKey) && typeof value === "string") try {
102
+ result[unmappedKey] = JSON.parse(value);
103
+ } catch {
104
+ result[unmappedKey] = value;
105
+ }
106
+ else result[unmappedKey] = value;
107
+ }
108
+ delete result.$loki;
109
+ delete result.meta;
110
+ return result;
111
+ }
112
+ async _create(key, attrs = {}, context) {
113
+ const sqlContext = context;
114
+ const executor = this.getExecutor(sqlContext);
115
+ const insertAttrs = { ...attrs };
116
+ if (Array.isArray(this.uniqIndex)) {
117
+ if (typeof key === "object") Object.assign(insertAttrs, key);
118
+ } else {
119
+ const id = this.generatePrimaryKey(key);
120
+ insertAttrs[this.primaryKey] = id;
121
+ }
122
+ const lookupKey = Array.isArray(this.uniqIndex) ? Object.fromEntries(this.uniqIndex.map((k) => [k, insertAttrs[k]])) : insertAttrs[this.primaryKey];
123
+ if (await SqliteTable.prototype._get.call(this, lookupKey, context)) throw new Error(`${this.name} already exists: ${JSON.stringify(key)}`);
124
+ if (this.syncBalance) delete insertAttrs.tokens;
125
+ const serialized = this.serializeForDb(insertAttrs);
126
+ await executor.insertInto(this.name).values(serialized).execute();
127
+ if (this.syncBalance && attrs.tokens) insertAttrs.tokens = await this.balanceTable.updateBalance({
128
+ address: insertAttrs.address,
129
+ tokens: attrs.tokens,
130
+ context: attrs.context
131
+ }, context);
132
+ return insertAttrs;
133
+ }
134
+ async _get(key, context) {
135
+ if (!key) return null;
136
+ const sqlContext = context;
137
+ const executor = this.getExecutor(sqlContext);
138
+ let query;
139
+ if (Array.isArray(this.uniqIndex)) if (typeof key === "object") {
140
+ const keyObj = key;
141
+ query = Object.fromEntries(this.uniqIndex.map((k) => [this.mapColumnName(k), keyObj[k]]));
142
+ } else return null;
143
+ else query = this.formatKeyToQuery(key);
144
+ let qb = executor.selectFrom(this.name).selectAll();
145
+ for (const [k, v] of Object.entries(query)) {
146
+ if (v === void 0) continue;
147
+ qb = qb.where(k, "=", v);
148
+ }
149
+ const result = await qb.executeTakeFirst();
150
+ const deserialized = this.deserializeFromDb(result);
151
+ if (deserialized && this.syncBalance) {
152
+ const balance = await this.balanceTable.getBalance(deserialized.address, context);
153
+ deserialized.tokens = {
154
+ ...deserialized.tokens || {},
155
+ ...balance
156
+ };
157
+ }
158
+ return deserialized;
159
+ }
160
+ _history(_key, _context) {
161
+ return [];
162
+ }
163
+ async _update(key, updates, context) {
164
+ const sqlContext = context;
165
+ const executor = this.getExecutor(sqlContext);
166
+ let lookupKey = key;
167
+ if (Array.isArray(this.uniqIndex) && typeof key !== "object") {
168
+ const updatesObj = updates;
169
+ lookupKey = Object.fromEntries(this.uniqIndex.map((k) => [k, updatesObj[k]]));
170
+ }
171
+ const existing = await SqliteTable.prototype._get.call(this, lookupKey, context);
172
+ if (!existing) throw new Error(`${this.name} does not exist: ${JSON.stringify(key)}`);
173
+ let query;
174
+ if (Array.isArray(this.uniqIndex)) {
175
+ const keyObj = typeof lookupKey === "object" ? lookupKey : existing;
176
+ query = Object.fromEntries(this.uniqIndex.map((k) => [this.mapColumnName(k), keyObj[k]]));
177
+ } else query = this.formatKeyToQuery(key);
178
+ const updateAttrs = { ...updates };
179
+ if (Array.isArray(this.uniqIndex)) for (const k of this.uniqIndex) delete updateAttrs[k];
180
+ else delete updateAttrs[this.primaryKey];
181
+ if (this.syncBalance) delete updateAttrs.tokens;
182
+ if (Object.keys(updateAttrs).length > 0) {
183
+ const serialized = this.serializeForDb(updateAttrs);
184
+ let qb = executor.updateTable(this.name).set(serialized);
185
+ for (const [k, v] of Object.entries(query)) {
186
+ if (v === void 0) continue;
187
+ qb = qb.where(k, "=", v);
188
+ }
189
+ await qb.execute();
190
+ }
191
+ const merged = {
192
+ ...existing,
193
+ ...updateAttrs
194
+ };
195
+ if (this.syncBalance && updates.tokens) merged.tokens = await this.balanceTable.updateBalance({
196
+ address: merged.address,
197
+ tokens: updates.tokens,
198
+ context: updates.context
199
+ }, context);
200
+ return merged;
201
+ }
202
+ async _reset(_context) {
203
+ const sqlContext = _context;
204
+ await this.getExecutor(sqlContext).deleteFrom(this.name).execute();
205
+ }
206
+ async updateOrCreate(exist, state, ctx) {
207
+ const id = this.generatePrimaryKey(state);
208
+ const attrs = omit(state, Array.isArray(this.uniqIndex) ? this.uniqIndex : [this.uniqIndex]);
209
+ if (!id) throw new Error("Cannot update or create without uniq index");
210
+ if (exist) return this.update(id, attrs, ctx);
211
+ return this.create(id, attrs, ctx);
212
+ }
213
+ };
214
+ var base_default = SqliteTable;
215
+
216
+ //#endregion
217
+ export { base_default as default };
@@ -0,0 +1,22 @@
1
+ import SqliteTable, { SqliteTableConfig } from "./base.mjs";
2
+ import { IOperationContext, IRollupState } from "@ocap/types";
3
+
4
+ //#region src/table/rollup.d.ts
5
+
6
+ /**
7
+ * Rollup Table
8
+ * Extends base table with tokenAddress-based existence check
9
+ */
10
+ declare class RollupTable extends SqliteTable<IRollupState> {
11
+ constructor(config: Omit<SqliteTableConfig, 'name' | 'uniqIndex' | 'schema'>);
12
+ /**
13
+ * Check if an active (non-paused) rollup with the given tokenAddress exists
14
+ *
15
+ * @param tokenAddress - Token address to check
16
+ * @param context - Operation context with optional transaction
17
+ * @returns true if active rollup with tokenAddress exists, false if tokenAddress is empty/undefined or rollup is paused
18
+ */
19
+ existByToken(tokenAddress: string, context?: IOperationContext): Promise<boolean>;
20
+ }
21
+ //#endregion
22
+ export { RollupTable as default };
@@ -0,0 +1,44 @@
1
+ import base_default from "./base.mjs";
2
+
3
+ //#region src/table/rollup.ts
4
+ /**
5
+ * Rollup Table
6
+ * Extends base table with tokenAddress-based existence check
7
+ */
8
+ var RollupTable = class extends base_default {
9
+ constructor(config) {
10
+ super({
11
+ ...config,
12
+ name: "rollup",
13
+ uniqIndex: "address",
14
+ schema: {
15
+ jsonFields: [
16
+ "seedValidators",
17
+ "validators",
18
+ "migrateHistory",
19
+ "vaultHistory",
20
+ "data",
21
+ "context"
22
+ ],
23
+ booleanFields: ["paused", "closed"]
24
+ }
25
+ });
26
+ }
27
+ /**
28
+ * Check if an active (non-paused) rollup with the given tokenAddress exists
29
+ *
30
+ * @param tokenAddress - Token address to check
31
+ * @param context - Operation context with optional transaction
32
+ * @returns true if active rollup with tokenAddress exists, false if tokenAddress is empty/undefined or rollup is paused
33
+ */
34
+ async existByToken(tokenAddress, context) {
35
+ if (!tokenAddress) return false;
36
+ const sqlContext = context;
37
+ const executor = this.getExecutor(sqlContext);
38
+ return ((await executor.selectFrom("rollup").select(executor.fn.count("address").as("count")).where("tokenAddress", "=", tokenAddress).where("paused", "=", 0).executeTakeFirst())?.count ?? 0) > 0;
39
+ }
40
+ };
41
+ var rollup_default = RollupTable;
42
+
43
+ //#endregion
44
+ export { rollup_default as default };
@@ -0,0 +1,23 @@
1
+ import SqliteTable, { SqliteTableConfig } from "./base.mjs";
2
+ import { IOperationContext, ITokenState } from "@ocap/types";
3
+
4
+ //#region src/table/token.d.ts
5
+
6
+ /**
7
+ * Token Table
8
+ * Extends base table with symbol-based existence check
9
+ */
10
+ declare class TokenTable extends SqliteTable<ITokenState> {
11
+ constructor(config: Omit<SqliteTableConfig, 'name' | 'uniqIndex' | 'schema'>);
12
+ /**
13
+ * Check if a token with the given symbol exists
14
+ *
15
+ * @param symbol - Token symbol to check
16
+ * @param context - Operation context with optional transaction
17
+ * @returns true if token with symbol exists
18
+ * @throws Error if symbol is empty
19
+ */
20
+ existBySymbol(symbol: string, context?: IOperationContext): Promise<boolean>;
21
+ }
22
+ //#endregion
23
+ export { TokenTable as default };
@@ -0,0 +1,42 @@
1
+ import base_default from "./base.mjs";
2
+
3
+ //#region src/table/token.ts
4
+ /**
5
+ * Token Table
6
+ * Extends base table with symbol-based existence check
7
+ */
8
+ var TokenTable = class extends base_default {
9
+ constructor(config) {
10
+ super({
11
+ ...config,
12
+ name: "token",
13
+ uniqIndex: "address",
14
+ schema: { jsonFields: [
15
+ "foreignToken",
16
+ "metadata",
17
+ "spenders",
18
+ "minters",
19
+ "data",
20
+ "context"
21
+ ] }
22
+ });
23
+ }
24
+ /**
25
+ * Check if a token with the given symbol exists
26
+ *
27
+ * @param symbol - Token symbol to check
28
+ * @param context - Operation context with optional transaction
29
+ * @returns true if token with symbol exists
30
+ * @throws Error if symbol is empty
31
+ */
32
+ async existBySymbol(symbol, context) {
33
+ if (!symbol) throw new Error("param symbol is required");
34
+ const sqlContext = context;
35
+ const executor = this.getExecutor(sqlContext);
36
+ return ((await executor.selectFrom("token").select(executor.fn.count("address").as("count")).where("symbol", "=", symbol).executeTakeFirst())?.count ?? 0) > 0;
37
+ }
38
+ };
39
+ var token_default = TokenTable;
40
+
41
+ //#endregion
42
+ export { token_default as default };
@@ -0,0 +1,43 @@
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 __exportAll = (all, symbols) => {
9
+ let target = {};
10
+ for (var name in all) {
11
+ __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ }
16
+ if (symbols) {
17
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
18
+ }
19
+ return target;
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") {
23
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
24
+ key = keys[i];
25
+ if (!__hasOwnProp.call(to, key) && key !== except) {
26
+ __defProp(to, key, {
27
+ get: ((k) => from[k]).bind(null, key),
28
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
29
+ });
30
+ }
31
+ }
32
+ }
33
+ return to;
34
+ };
35
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
36
+ value: mod,
37
+ enumerable: true
38
+ }) : target, mod));
39
+
40
+ //#endregion
41
+
42
+ exports.__exportAll = __exportAll;
43
+ exports.__toESM = __toESM;
package/lib/db.cjs ADDED
@@ -0,0 +1,259 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
3
+ const require_kysely = require('./kysely.cjs');
4
+ const require_migrations_index = require('./migrations/index.cjs');
5
+ const require_table_base = require('./table/base.cjs');
6
+ const require_table_account = require('./table/account.cjs');
7
+ const require_table_balance = require('./table/balance.cjs');
8
+ const require_table_rollup = require('./table/rollup.cjs');
9
+ const require_table_token = require('./table/token.cjs');
10
+ const require_package = require('./package.cjs');
11
+ let _ocap_statedb = require("@ocap/statedb");
12
+
13
+ //#region src/db.ts
14
+ const { name, version } = require_package.default;
15
+ const SQLITE_BUSY_CODES = ["SQLITE_BUSY", "SQLITE_LOCKED"];
16
+ /**
17
+ * SQLite StateDB Implementation
18
+ * Uses SQLite via Kysely as the storage backend
19
+ */
20
+ var SqliteStateDB = class extends _ocap_statedb.StateDB {
21
+ /**
22
+ * Creates an instance of SqliteStateDB
23
+ *
24
+ * @param config - SQLite configuration (defaults to in-memory)
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // In-memory database for testing
29
+ * const db = new SqliteStateDB();
30
+ * await db.initialize();
31
+ *
32
+ * // File-based database for production
33
+ * const db = new SqliteStateDB({ filename: './data/state.sqlite' });
34
+ * await db.initialize();
35
+ * ```
36
+ */
37
+ constructor(config = { filename: ":memory:" }) {
38
+ super();
39
+ this.initialized = false;
40
+ this.name = name;
41
+ this.version = version;
42
+ this.config = config;
43
+ this.initSync();
44
+ }
45
+ /**
46
+ * Synchronous initialization
47
+ * Called from constructor for immediate table availability
48
+ */
49
+ initSync() {
50
+ this.db = require_kysely.createKysely(this.config);
51
+ this.balance = new require_table_balance.default({ db: this.db });
52
+ this.account = new require_table_account.default({
53
+ db: this.db,
54
+ syncBalance: true,
55
+ balanceTable: this.balance
56
+ });
57
+ this.factory = new require_table_base.default({
58
+ name: "factory",
59
+ uniqIndex: "address",
60
+ db: this.db,
61
+ syncBalance: true,
62
+ balanceTable: this.balance,
63
+ schema: { jsonFields: [
64
+ "trustedIssuers",
65
+ "tokens",
66
+ "input",
67
+ "output",
68
+ "display",
69
+ "hooks",
70
+ "data",
71
+ "context",
72
+ "stake"
73
+ ] }
74
+ });
75
+ this.stake = new require_table_base.default({
76
+ name: "stake",
77
+ uniqIndex: "address",
78
+ db: this.db,
79
+ syncBalance: true,
80
+ balanceTable: this.balance,
81
+ schema: {
82
+ jsonFields: [
83
+ "tokens",
84
+ "assets",
85
+ "slashers",
86
+ "revokedTokens",
87
+ "revokedAssets",
88
+ "data",
89
+ "context"
90
+ ],
91
+ booleanFields: ["revocable"]
92
+ }
93
+ });
94
+ this.asset = new require_table_base.default({
95
+ name: "asset",
96
+ uniqIndex: "address",
97
+ db: this.db,
98
+ schema: {
99
+ jsonFields: [
100
+ "endpoint",
101
+ "display",
102
+ "tags",
103
+ "stake",
104
+ "data",
105
+ "context"
106
+ ],
107
+ booleanFields: ["readonly", "transferrable"]
108
+ }
109
+ });
110
+ this.delegation = new require_table_base.default({
111
+ name: "delegation",
112
+ uniqIndex: "address",
113
+ db: this.db,
114
+ schema: {
115
+ jsonFields: [
116
+ "ops",
117
+ "data",
118
+ "context"
119
+ ],
120
+ columnMapping: {
121
+ from: "from_",
122
+ to: "to_"
123
+ }
124
+ }
125
+ });
126
+ this.tx = new require_table_base.default({
127
+ name: "tx",
128
+ uniqIndex: "hash",
129
+ db: this.db,
130
+ schema: {
131
+ jsonFields: [
132
+ "receipts",
133
+ "tx",
134
+ "context"
135
+ ],
136
+ columnMapping: { index: "index_" },
137
+ booleanFields: [
138
+ "receiptsVerified",
139
+ "finalized",
140
+ "valid"
141
+ ]
142
+ }
143
+ });
144
+ this.token = new require_table_token.default({ db: this.db });
145
+ this.chain = new require_table_base.default({
146
+ name: "chain",
147
+ uniqIndex: "address",
148
+ db: this.db,
149
+ schema: { jsonFields: [
150
+ "accounts",
151
+ "moderator",
152
+ "token",
153
+ "transaction",
154
+ "vaults",
155
+ "context"
156
+ ] }
157
+ });
158
+ this.rollup = new require_table_rollup.default({ db: this.db });
159
+ this.rollupBlock = new require_table_base.default({
160
+ name: "rollupBlock",
161
+ uniqIndex: "hash",
162
+ db: this.db,
163
+ schema: {
164
+ jsonFields: [
165
+ "txs",
166
+ "signatures",
167
+ "data",
168
+ "context"
169
+ ],
170
+ booleanFields: ["governance"]
171
+ }
172
+ });
173
+ this.evidence = new require_table_base.default({
174
+ name: "evidence",
175
+ uniqIndex: "hash",
176
+ db: this.db,
177
+ schema: { jsonFields: ["data", "context"] }
178
+ });
179
+ this.tokenFactory = new require_table_base.default({
180
+ name: "tokenFactory",
181
+ uniqIndex: "address",
182
+ db: this.db,
183
+ schema: { jsonFields: [
184
+ "curve",
185
+ "input",
186
+ "output",
187
+ "data",
188
+ "context"
189
+ ] }
190
+ });
191
+ this.attachReadyListeners();
192
+ }
193
+ /**
194
+ * Async initialization - runs migrations
195
+ * Call this after constructor to ensure database schema is ready
196
+ */
197
+ async initialize() {
198
+ if (this.initialized) return;
199
+ await require_migrations_index.runMigrations(this.db);
200
+ this.initialized = true;
201
+ }
202
+ /**
203
+ * Execute multiple operations within a database transaction
204
+ * Provides retry logic for SQLite BUSY errors (lock conflicts)
205
+ *
206
+ * @param fn - Function receiving Kysely transaction object
207
+ * @param options - Optional retry configuration
208
+ * @returns Result of the transaction function
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * await db.runAsLambda(async (txn) => {
213
+ * await txn.insertInto('account').values({ ... }).execute();
214
+ * await txn.updateTable('balance').set({ ... }).execute();
215
+ * });
216
+ * ```
217
+ */
218
+ async runAsLambda(fn, options = {}) {
219
+ const { retryLimit = 2 } = options;
220
+ let lastError;
221
+ for (let attempt = 0; attempt <= retryLimit; attempt++) try {
222
+ return await this.db.transaction().execute(async (txn) => {
223
+ return await fn(txn);
224
+ });
225
+ } catch (err) {
226
+ lastError = err;
227
+ const code = err?.code;
228
+ if (!SQLITE_BUSY_CODES.includes(code)) throw err;
229
+ if (attempt < retryLimit) await new Promise((r) => setTimeout(r, 10 * 2 ** attempt));
230
+ }
231
+ throw lastError;
232
+ }
233
+ /**
234
+ * Reset all tables (for testing)
235
+ */
236
+ async reset() {
237
+ const tables = Object.keys(this.readyMarks);
238
+ for (const table of tables) {
239
+ const tableInstance = this[table];
240
+ if (tableInstance?.reset) await tableInstance.reset();
241
+ }
242
+ }
243
+ /**
244
+ * Close database connection
245
+ */
246
+ async close() {
247
+ await this.db.destroy();
248
+ }
249
+ /**
250
+ * Get the underlying Kysely instance (for advanced operations)
251
+ */
252
+ getKysely() {
253
+ return this.db;
254
+ }
255
+ };
256
+ var db_default = SqliteStateDB;
257
+
258
+ //#endregion
259
+ exports.default = db_default;