@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,101 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
3
+ const require_table_base = require('./base.cjs');
4
+ let _ocap_state_lib_states_account = require("@ocap/state/lib/states/account");
5
+
6
+ //#region src/table/account.ts
7
+ /**
8
+ * Account Table
9
+ * Standard account state with balance sync support
10
+ * Includes migration chain following and circular migration detection
11
+ */
12
+ var AccountTable = class extends require_table_base.default {
13
+ constructor(config) {
14
+ super({
15
+ ...config,
16
+ name: "account",
17
+ uniqIndex: "address",
18
+ schema: { jsonFields: [
19
+ "migratedTo",
20
+ "migratedFrom",
21
+ "stake",
22
+ "tokens",
23
+ "data",
24
+ "context",
25
+ "poke"
26
+ ] }
27
+ });
28
+ }
29
+ /**
30
+ * Check if adding migration targets would create a cycle
31
+ * @param sourceAddress - The address that will have migratedTo set
32
+ * @param targets - The migration targets to check
33
+ * @param context - Operation context with transaction
34
+ * @returns true if a cycle would be created
35
+ */
36
+ async wouldCreateCycle(sourceAddress, targets, context) {
37
+ const visited = /* @__PURE__ */ new Set();
38
+ visited.add(sourceAddress);
39
+ const checkTarget = async (target) => {
40
+ const normalizedTarget = (0, _ocap_state_lib_states_account.ensureChecksumAddress)(target);
41
+ if (normalizedTarget === sourceAddress) return true;
42
+ if (visited.has(normalizedTarget)) return false;
43
+ visited.add(normalizedTarget);
44
+ const targetAccount = await super._get(normalizedTarget, context);
45
+ if (targetAccount?.migratedTo?.length) {
46
+ for (const nextTarget of targetAccount.migratedTo) if (await checkTarget(nextTarget)) return true;
47
+ }
48
+ return false;
49
+ };
50
+ for (const target of targets) if (await checkTarget(target)) return true;
51
+ return false;
52
+ }
53
+ /**
54
+ * Get account with migration chain following
55
+ * When an account has migratedTo set, follows the chain to get the final account
56
+ */
57
+ async _get(address, context = {}) {
58
+ const { traceMigration = true, ...restContext } = context;
59
+ const normalizedAddress = (0, _ocap_state_lib_states_account.ensureChecksumAddress)(address);
60
+ const current = await super._get(normalizedAddress, restContext);
61
+ if (current && traceMigration && Array.isArray(current.migratedTo) && current.migratedTo.length) {
62
+ const visitedAddresses = context._visitedAddresses || /* @__PURE__ */ new Set();
63
+ if (visitedAddresses.has(normalizedAddress)) return null;
64
+ visitedAddresses.add(normalizedAddress);
65
+ return this._get(current.migratedTo[0], {
66
+ ...context,
67
+ _visitedAddresses: visitedAddresses
68
+ });
69
+ }
70
+ return current;
71
+ }
72
+ /**
73
+ * Create account with address normalization and circular migration detection
74
+ */
75
+ async _create(key, attrs = {}, context) {
76
+ const address = (0, _ocap_state_lib_states_account.ensureChecksumAddress)(key);
77
+ const attrsWithMigration = attrs;
78
+ if (attrsWithMigration.migratedTo?.length) {
79
+ if (await this.wouldCreateCycle(address, attrsWithMigration.migratedTo, context)) throw new Error(`Circular migration detected: ${address} -> ${attrsWithMigration.migratedTo.join(", ")}`);
80
+ }
81
+ return super._create(address, {
82
+ ...attrs,
83
+ [this.uniqIndex]: address
84
+ }, context);
85
+ }
86
+ /**
87
+ * Update account with circular migration detection
88
+ */
89
+ async _update(key, updates, context) {
90
+ const address = (0, _ocap_state_lib_states_account.ensureChecksumAddress)(key);
91
+ const updatesWithMigration = updates;
92
+ if (updatesWithMigration.migratedTo?.length) {
93
+ if (await this.wouldCreateCycle(address, updatesWithMigration.migratedTo, context)) throw new Error(`Circular migration detected: ${address} -> ${updatesWithMigration.migratedTo.join(", ")}`);
94
+ }
95
+ return super._update(address, updates, context);
96
+ }
97
+ };
98
+ var account_default = AccountTable;
99
+
100
+ //#endregion
101
+ exports.default = account_default;
@@ -0,0 +1,40 @@
1
+ import SqliteTable, { SqliteTableConfig } from "./base.cjs";
2
+ import { IAccountState, IOperationContext } from "@ocap/types";
3
+
4
+ //#region src/table/account.d.ts
5
+ interface AccountOperationContext extends IOperationContext {
6
+ traceMigration?: boolean;
7
+ /** Internal: tracks visited addresses to detect circular migrations */
8
+ _visitedAddresses?: Set<string>;
9
+ }
10
+ /**
11
+ * Account Table
12
+ * Standard account state with balance sync support
13
+ * Includes migration chain following and circular migration detection
14
+ */
15
+ declare class AccountTable extends SqliteTable<IAccountState> {
16
+ constructor(config: Omit<SqliteTableConfig, 'name' | 'uniqIndex' | 'schema'>);
17
+ /**
18
+ * Check if adding migration targets would create a cycle
19
+ * @param sourceAddress - The address that will have migratedTo set
20
+ * @param targets - The migration targets to check
21
+ * @param context - Operation context with transaction
22
+ * @returns true if a cycle would be created
23
+ */
24
+ private wouldCreateCycle;
25
+ /**
26
+ * Get account with migration chain following
27
+ * When an account has migratedTo set, follows the chain to get the final account
28
+ */
29
+ _get(address: string, context?: AccountOperationContext): Promise<IAccountState | null>;
30
+ /**
31
+ * Create account with address normalization and circular migration detection
32
+ */
33
+ _create(key: string, attrs?: Partial<IAccountState>, context?: IOperationContext): Promise<IAccountState>;
34
+ /**
35
+ * Update account with circular migration detection
36
+ */
37
+ _update(key: string, updates: Partial<IAccountState>, context?: IOperationContext): Promise<IAccountState>;
38
+ }
39
+ //#endregion
40
+ export { AccountTable as default };
@@ -0,0 +1,71 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
3
+ const require_table_base = require('./base.cjs');
4
+ let _ocap_state_lib_states_account = require("@ocap/state/lib/states/account");
5
+
6
+ //#region src/table/balance.ts
7
+ /**
8
+ * Balance Table
9
+ * Manages token balances with composite primary key (address, tokenAddress)
10
+ */
11
+ var BalanceTable = class extends require_table_base.default {
12
+ constructor(config) {
13
+ super({
14
+ ...config,
15
+ name: "balance",
16
+ uniqIndex: ["address", "tokenAddress"],
17
+ schema: { jsonFields: ["context"] }
18
+ });
19
+ }
20
+ /**
21
+ * Get all token balances for an address
22
+ *
23
+ * @param address - Account address
24
+ * @param _context - Operation context
25
+ * @returns Object mapping tokenAddress to balance
26
+ */
27
+ async getBalance(address, _context) {
28
+ const sqlContext = _context;
29
+ const executor = this.getExecutor(sqlContext);
30
+ const normalizedAddress = (0, _ocap_state_lib_states_account.ensureChecksumAddress)(address);
31
+ return (await executor.selectFrom("balance").selectAll().where("address", "=", normalizedAddress).execute() || []).reduce((acc, token) => {
32
+ acc[token.tokenAddress] = token.balance;
33
+ return acc;
34
+ }, {});
35
+ }
36
+ /**
37
+ * Update token balances for an address
38
+ * Creates new records for new tokens, updates existing ones
39
+ *
40
+ * @param params - Update parameters
41
+ * @param ctx - Operation context
42
+ * @returns Updated token balances
43
+ */
44
+ async updateBalance({ address, tokens, context = {} }, ctx) {
45
+ if (!Object.keys(tokens).length) return {};
46
+ const tokenBalances = await this.getBalance(address, ctx);
47
+ const updatedTokens = Object.keys(tokens).filter((token) => tokenBalances[token] && tokenBalances[token] !== "0" || tokens[token] && tokens[token] !== "0").filter((token) => tokenBalances[token] !== tokens[token]);
48
+ await Promise.all(updatedTokens.map(async (tokenAddress) => {
49
+ const key = {
50
+ address,
51
+ tokenAddress
52
+ };
53
+ if (tokenBalances[tokenAddress]) await this.update(key, {
54
+ ...key,
55
+ balance: tokens[tokenAddress],
56
+ context
57
+ }, ctx);
58
+ else await this.create(key, {
59
+ ...key,
60
+ balance: tokens[tokenAddress],
61
+ context
62
+ }, ctx);
63
+ tokenBalances[tokenAddress] = tokens[tokenAddress];
64
+ }));
65
+ return tokens;
66
+ }
67
+ };
68
+ var balance_default = BalanceTable;
69
+
70
+ //#endregion
71
+ exports.default = balance_default;
@@ -0,0 +1,39 @@
1
+ import SqliteTable, { SqliteTableConfig } from "./base.cjs";
2
+ import { IBalanceState, IOperationContext } from "@ocap/types";
3
+
4
+ //#region src/table/balance.d.ts
5
+
6
+ /**
7
+ * Balance Table
8
+ * Manages token balances with composite primary key (address, tokenAddress)
9
+ */
10
+ declare class BalanceTable extends SqliteTable<IBalanceState> {
11
+ constructor(config: Omit<SqliteTableConfig, 'name' | 'uniqIndex' | 'schema'>);
12
+ /**
13
+ * Get all token balances for an address
14
+ *
15
+ * @param address - Account address
16
+ * @param _context - Operation context
17
+ * @returns Object mapping tokenAddress to balance
18
+ */
19
+ getBalance(address: string, _context?: IOperationContext): Promise<Record<string, string>>;
20
+ /**
21
+ * Update token balances for an address
22
+ * Creates new records for new tokens, updates existing ones
23
+ *
24
+ * @param params - Update parameters
25
+ * @param ctx - Operation context
26
+ * @returns Updated token balances
27
+ */
28
+ updateBalance({
29
+ address,
30
+ tokens,
31
+ context
32
+ }: {
33
+ address: string;
34
+ tokens: Record<string, string>;
35
+ context?: unknown;
36
+ }, ctx?: IOperationContext): Promise<Record<string, string>>;
37
+ }
38
+ //#endregion
39
+ export { BalanceTable as default };
@@ -0,0 +1,221 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
3
+ let _ocap_statedb = require("@ocap/statedb");
4
+ let node_crypto = require("node:crypto");
5
+ node_crypto = require_rolldown_runtime.__toESM(node_crypto);
6
+ let lodash_omit = require("lodash/omit");
7
+ lodash_omit = require_rolldown_runtime.__toESM(lodash_omit);
8
+
9
+ //#region src/table/base.ts
10
+ /**
11
+ * SQLite State Table base class
12
+ * Extends StateDBTable to provide SQLite-specific implementation
13
+ */
14
+ var SqliteTable = class SqliteTable extends _ocap_statedb.StateDBTable {
15
+ constructor(config) {
16
+ super(config.uniqIndex);
17
+ this.name = config.name;
18
+ this.db = config.db;
19
+ this.schema = config.schema || {};
20
+ this.balanceTable = config.balanceTable;
21
+ this.syncBalance = config.syncBalance ?? false;
22
+ if (this.syncBalance && !this.balanceTable) throw new Error("balanceTable is required when syncBalance is true");
23
+ this.markReady();
24
+ }
25
+ /**
26
+ * Get the Kysely executor (use transaction if available)
27
+ */
28
+ getExecutor(context) {
29
+ return context?.txn || this.db;
30
+ }
31
+ /**
32
+ * Generate primary key from document
33
+ * Handles both simple string keys and composite keys
34
+ */
35
+ generatePrimaryKey(doc) {
36
+ if (typeof doc === "string") return doc;
37
+ if (Array.isArray(this.uniqIndex)) {
38
+ const key = this.uniqIndex.map((id) => doc[id]).map((item) => typeof item === "object" ? JSON.stringify(item) : item).join("-");
39
+ return node_crypto.default.createHash("md5").update(key).digest("hex");
40
+ }
41
+ return doc[this.uniqIndex];
42
+ }
43
+ /**
44
+ * Convert a key to a query object
45
+ */
46
+ formatKeyToQuery(key) {
47
+ if (Array.isArray(this.uniqIndex) && typeof key === "object") {
48
+ const keyObj = key;
49
+ return Object.fromEntries(this.uniqIndex.map((k) => [this.mapColumnName(k), keyObj[k]]));
50
+ }
51
+ if (typeof key === "object") {
52
+ const keyObj = key;
53
+ return { [this.mapColumnName(this.primaryKey)]: keyObj[this.primaryKey] };
54
+ }
55
+ return { [this.mapColumnName(this.primaryKey)]: key };
56
+ }
57
+ /**
58
+ * Map column name for reserved keywords
59
+ */
60
+ mapColumnName(name) {
61
+ return this.schema.columnMapping?.[name] ?? name;
62
+ }
63
+ /**
64
+ * Reverse map column name
65
+ */
66
+ unmapColumnName(name) {
67
+ const mapping = this.schema.columnMapping;
68
+ if (!mapping) return name;
69
+ for (const [original, mapped] of Object.entries(mapping)) if (mapped === name) return original;
70
+ return name;
71
+ }
72
+ /**
73
+ * Serialize data for database insert
74
+ * - Converts objects/arrays to JSON strings
75
+ * - Converts booleans to integers (0/1) for SQLite
76
+ * - Maps column names for reserved keywords
77
+ */
78
+ serializeForDb(data) {
79
+ const result = {};
80
+ const jsonFields = new Set(this.schema.jsonFields || []);
81
+ const booleanFields = new Set(this.schema.booleanFields || []);
82
+ for (const [key, value] of Object.entries(data)) {
83
+ const mappedKey = this.mapColumnName(key);
84
+ if (value === void 0) result[mappedKey] = null;
85
+ else if (booleanFields.has(key) && typeof value === "boolean") result[mappedKey] = value ? 1 : 0;
86
+ else if (jsonFields.has(key) || value !== null && typeof value === "object") result[mappedKey] = JSON.stringify(value);
87
+ else result[mappedKey] = value;
88
+ }
89
+ return result;
90
+ }
91
+ /**
92
+ * Deserialize data from database read
93
+ * - Parses JSON strings back to objects
94
+ * - Converts integers (0/1) back to booleans
95
+ * - Unmaps column names
96
+ */
97
+ deserializeFromDb(data) {
98
+ if (!data) return null;
99
+ const result = {};
100
+ const jsonFields = new Set(this.schema.jsonFields || []);
101
+ const booleanFields = new Set(this.schema.booleanFields || []);
102
+ for (const [key, value] of Object.entries(data)) {
103
+ const unmappedKey = this.unmapColumnName(key);
104
+ if (booleanFields.has(unmappedKey) && typeof value === "number") result[unmappedKey] = value === 1;
105
+ else if (jsonFields.has(unmappedKey) && typeof value === "string") try {
106
+ result[unmappedKey] = JSON.parse(value);
107
+ } catch {
108
+ result[unmappedKey] = value;
109
+ }
110
+ else result[unmappedKey] = value;
111
+ }
112
+ delete result.$loki;
113
+ delete result.meta;
114
+ return result;
115
+ }
116
+ async _create(key, attrs = {}, context) {
117
+ const sqlContext = context;
118
+ const executor = this.getExecutor(sqlContext);
119
+ const insertAttrs = { ...attrs };
120
+ if (Array.isArray(this.uniqIndex)) {
121
+ if (typeof key === "object") Object.assign(insertAttrs, key);
122
+ } else {
123
+ const id = this.generatePrimaryKey(key);
124
+ insertAttrs[this.primaryKey] = id;
125
+ }
126
+ const lookupKey = Array.isArray(this.uniqIndex) ? Object.fromEntries(this.uniqIndex.map((k) => [k, insertAttrs[k]])) : insertAttrs[this.primaryKey];
127
+ if (await SqliteTable.prototype._get.call(this, lookupKey, context)) throw new Error(`${this.name} already exists: ${JSON.stringify(key)}`);
128
+ if (this.syncBalance) delete insertAttrs.tokens;
129
+ const serialized = this.serializeForDb(insertAttrs);
130
+ await executor.insertInto(this.name).values(serialized).execute();
131
+ if (this.syncBalance && attrs.tokens) insertAttrs.tokens = await this.balanceTable.updateBalance({
132
+ address: insertAttrs.address,
133
+ tokens: attrs.tokens,
134
+ context: attrs.context
135
+ }, context);
136
+ return insertAttrs;
137
+ }
138
+ async _get(key, context) {
139
+ if (!key) return null;
140
+ const sqlContext = context;
141
+ const executor = this.getExecutor(sqlContext);
142
+ let query;
143
+ if (Array.isArray(this.uniqIndex)) if (typeof key === "object") {
144
+ const keyObj = key;
145
+ query = Object.fromEntries(this.uniqIndex.map((k) => [this.mapColumnName(k), keyObj[k]]));
146
+ } else return null;
147
+ else query = this.formatKeyToQuery(key);
148
+ let qb = executor.selectFrom(this.name).selectAll();
149
+ for (const [k, v] of Object.entries(query)) {
150
+ if (v === void 0) continue;
151
+ qb = qb.where(k, "=", v);
152
+ }
153
+ const result = await qb.executeTakeFirst();
154
+ const deserialized = this.deserializeFromDb(result);
155
+ if (deserialized && this.syncBalance) {
156
+ const balance = await this.balanceTable.getBalance(deserialized.address, context);
157
+ deserialized.tokens = {
158
+ ...deserialized.tokens || {},
159
+ ...balance
160
+ };
161
+ }
162
+ return deserialized;
163
+ }
164
+ _history(_key, _context) {
165
+ return [];
166
+ }
167
+ async _update(key, updates, context) {
168
+ const sqlContext = context;
169
+ const executor = this.getExecutor(sqlContext);
170
+ let lookupKey = key;
171
+ if (Array.isArray(this.uniqIndex) && typeof key !== "object") {
172
+ const updatesObj = updates;
173
+ lookupKey = Object.fromEntries(this.uniqIndex.map((k) => [k, updatesObj[k]]));
174
+ }
175
+ const existing = await SqliteTable.prototype._get.call(this, lookupKey, context);
176
+ if (!existing) throw new Error(`${this.name} does not exist: ${JSON.stringify(key)}`);
177
+ let query;
178
+ if (Array.isArray(this.uniqIndex)) {
179
+ const keyObj = typeof lookupKey === "object" ? lookupKey : existing;
180
+ query = Object.fromEntries(this.uniqIndex.map((k) => [this.mapColumnName(k), keyObj[k]]));
181
+ } else query = this.formatKeyToQuery(key);
182
+ const updateAttrs = { ...updates };
183
+ if (Array.isArray(this.uniqIndex)) for (const k of this.uniqIndex) delete updateAttrs[k];
184
+ else delete updateAttrs[this.primaryKey];
185
+ if (this.syncBalance) delete updateAttrs.tokens;
186
+ if (Object.keys(updateAttrs).length > 0) {
187
+ const serialized = this.serializeForDb(updateAttrs);
188
+ let qb = executor.updateTable(this.name).set(serialized);
189
+ for (const [k, v] of Object.entries(query)) {
190
+ if (v === void 0) continue;
191
+ qb = qb.where(k, "=", v);
192
+ }
193
+ await qb.execute();
194
+ }
195
+ const merged = {
196
+ ...existing,
197
+ ...updateAttrs
198
+ };
199
+ if (this.syncBalance && updates.tokens) merged.tokens = await this.balanceTable.updateBalance({
200
+ address: merged.address,
201
+ tokens: updates.tokens,
202
+ context: updates.context
203
+ }, context);
204
+ return merged;
205
+ }
206
+ async _reset(_context) {
207
+ const sqlContext = _context;
208
+ await this.getExecutor(sqlContext).deleteFrom(this.name).execute();
209
+ }
210
+ async updateOrCreate(exist, state, ctx) {
211
+ const id = this.generatePrimaryKey(state);
212
+ const attrs = (0, lodash_omit.default)(state, Array.isArray(this.uniqIndex) ? this.uniqIndex : [this.uniqIndex]);
213
+ if (!id) throw new Error("Cannot update or create without uniq index");
214
+ if (exist) return this.update(id, attrs, ctx);
215
+ return this.create(id, attrs, ctx);
216
+ }
217
+ };
218
+ var base_default = SqliteTable;
219
+
220
+ //#endregion
221
+ exports.default = base_default;
@@ -0,0 +1,84 @@
1
+ import { Database, SqliteOperationContext } from "../interfaces.cjs";
2
+ import { StateDBTable } from "@ocap/statedb";
3
+ import { IBalanceTable, IOperationContext } from "@ocap/types";
4
+ import { Kysely, Transaction } from "kysely";
5
+
6
+ //#region src/table/base.d.ts
7
+
8
+ /**
9
+ * Table schema configuration
10
+ */
11
+ interface TableSchema {
12
+ /** Column names that contain JSON data */
13
+ jsonFields?: string[];
14
+ /** Column names that contain boolean data (stored as integer 0/1 in SQLite) */
15
+ booleanFields?: string[];
16
+ /** Column name mapping (e.g., 'from' -> 'from_' for reserved keywords) */
17
+ columnMapping?: Record<string, string>;
18
+ }
19
+ /**
20
+ * Table configuration
21
+ */
22
+ interface SqliteTableConfig {
23
+ name: string;
24
+ uniqIndex: string | string[];
25
+ db: Kysely<Database>;
26
+ schema?: TableSchema;
27
+ syncBalance?: boolean;
28
+ balanceTable?: IBalanceTable;
29
+ }
30
+ /**
31
+ * SQLite State Table base class
32
+ * Extends StateDBTable to provide SQLite-specific implementation
33
+ */
34
+ declare class SqliteTable<T = unknown> extends StateDBTable<T> {
35
+ name: string;
36
+ db: Kysely<Database>;
37
+ schema: TableSchema;
38
+ balanceTable?: IBalanceTable;
39
+ syncBalance: boolean;
40
+ constructor(config: SqliteTableConfig);
41
+ /**
42
+ * Get the Kysely executor (use transaction if available)
43
+ */
44
+ protected getExecutor(context?: SqliteOperationContext): Kysely<Database> | Transaction<Database>;
45
+ /**
46
+ * Generate primary key from document
47
+ * Handles both simple string keys and composite keys
48
+ */
49
+ generatePrimaryKey(doc: string | Record<string, unknown>): string;
50
+ /**
51
+ * Convert a key to a query object
52
+ */
53
+ protected formatKeyToQuery(key: unknown): Record<string, unknown>;
54
+ /**
55
+ * Map column name for reserved keywords
56
+ */
57
+ protected mapColumnName(name: string): string;
58
+ /**
59
+ * Reverse map column name
60
+ */
61
+ protected unmapColumnName(name: string): string;
62
+ /**
63
+ * Serialize data for database insert
64
+ * - Converts objects/arrays to JSON strings
65
+ * - Converts booleans to integers (0/1) for SQLite
66
+ * - Maps column names for reserved keywords
67
+ */
68
+ protected serializeForDb(data: Record<string, unknown>): Record<string, unknown>;
69
+ /**
70
+ * Deserialize data from database read
71
+ * - Parses JSON strings back to objects
72
+ * - Converts integers (0/1) back to booleans
73
+ * - Unmaps column names
74
+ */
75
+ protected deserializeFromDb(data: Record<string, unknown> | undefined | null): Record<string, unknown> | null;
76
+ _create(key: string | Record<string, unknown>, attrs?: Partial<T>, context?: IOperationContext): Promise<T>;
77
+ _get(key: string | Record<string, unknown>, context?: IOperationContext): Promise<T | null>;
78
+ _history(_key?: string, _context?: IOperationContext): T[];
79
+ _update(key: string | Record<string, unknown>, updates: Partial<T>, context?: IOperationContext): Promise<T>;
80
+ _reset(_context?: IOperationContext): Promise<void>;
81
+ updateOrCreate(exist: unknown, state: Partial<T>, ctx?: IOperationContext): Promise<T>;
82
+ }
83
+ //#endregion
84
+ export { SqliteTableConfig, TableSchema, SqliteTable as default };
@@ -0,0 +1,45 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_table_base = require('./base.cjs');
3
+
4
+ //#region src/table/rollup.ts
5
+ /**
6
+ * Rollup Table
7
+ * Extends base table with tokenAddress-based existence check
8
+ */
9
+ var RollupTable = class extends require_table_base.default {
10
+ constructor(config) {
11
+ super({
12
+ ...config,
13
+ name: "rollup",
14
+ uniqIndex: "address",
15
+ schema: {
16
+ jsonFields: [
17
+ "seedValidators",
18
+ "validators",
19
+ "migrateHistory",
20
+ "vaultHistory",
21
+ "data",
22
+ "context"
23
+ ],
24
+ booleanFields: ["paused", "closed"]
25
+ }
26
+ });
27
+ }
28
+ /**
29
+ * Check if an active (non-paused) rollup with the given tokenAddress exists
30
+ *
31
+ * @param tokenAddress - Token address to check
32
+ * @param context - Operation context with optional transaction
33
+ * @returns true if active rollup with tokenAddress exists, false if tokenAddress is empty/undefined or rollup is paused
34
+ */
35
+ async existByToken(tokenAddress, context) {
36
+ if (!tokenAddress) return false;
37
+ const sqlContext = context;
38
+ const executor = this.getExecutor(sqlContext);
39
+ return ((await executor.selectFrom("rollup").select(executor.fn.count("address").as("count")).where("tokenAddress", "=", tokenAddress).where("paused", "=", 0).executeTakeFirst())?.count ?? 0) > 0;
40
+ }
41
+ };
42
+ var rollup_default = RollupTable;
43
+
44
+ //#endregion
45
+ exports.default = rollup_default;
@@ -0,0 +1,22 @@
1
+ import SqliteTable, { SqliteTableConfig } from "./base.cjs";
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,43 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_table_base = require('./base.cjs');
3
+
4
+ //#region src/table/token.ts
5
+ /**
6
+ * Token Table
7
+ * Extends base table with symbol-based existence check
8
+ */
9
+ var TokenTable = class extends require_table_base.default {
10
+ constructor(config) {
11
+ super({
12
+ ...config,
13
+ name: "token",
14
+ uniqIndex: "address",
15
+ schema: { jsonFields: [
16
+ "foreignToken",
17
+ "metadata",
18
+ "spenders",
19
+ "minters",
20
+ "data",
21
+ "context"
22
+ ] }
23
+ });
24
+ }
25
+ /**
26
+ * Check if a token with the given symbol exists
27
+ *
28
+ * @param symbol - Token symbol to check
29
+ * @param context - Operation context with optional transaction
30
+ * @returns true if token with symbol exists
31
+ * @throws Error if symbol is empty
32
+ */
33
+ async existBySymbol(symbol, context) {
34
+ if (!symbol) throw new Error("param symbol is required");
35
+ const sqlContext = context;
36
+ const executor = this.getExecutor(sqlContext);
37
+ return ((await executor.selectFrom("token").select(executor.fn.count("address").as("count")).where("symbol", "=", symbol).executeTakeFirst())?.count ?? 0) > 0;
38
+ }
39
+ };
40
+ var token_default = TokenTable;
41
+
42
+ //#endregion
43
+ exports.default = token_default;