@fadhilp/stateql 0.5.2 → 0.5.3
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/dist/src/migrations.js +10 -0
- package/dist/src/stateql.js +15 -5
- package/dist/src/store.d.ts +2 -0
- package/dist/src/store.js +20 -3
- package/dist/src/types.d.ts +1 -0
- package/package.json +1 -1
package/dist/src/migrations.js
CHANGED
|
@@ -46,6 +46,15 @@ const MIGRATIONS = [
|
|
|
46
46
|
apply: migrateSharedSessionActors,
|
|
47
47
|
validate: validateSharedSessionActors,
|
|
48
48
|
},
|
|
49
|
+
{
|
|
50
|
+
name: "history_sql_v1",
|
|
51
|
+
apply(db) {
|
|
52
|
+
addColumn(db, "history", "sql", "TEXT");
|
|
53
|
+
},
|
|
54
|
+
validate(db) {
|
|
55
|
+
requireColumns(db, "history", ["sql"]);
|
|
56
|
+
},
|
|
57
|
+
},
|
|
49
58
|
];
|
|
50
59
|
export function runMigrations(db, now) {
|
|
51
60
|
db.exec(`
|
|
@@ -202,6 +211,7 @@ function createInitialSchema(db) {
|
|
|
202
211
|
session_id TEXT NOT NULL,
|
|
203
212
|
actor_id TEXT NOT NULL,
|
|
204
213
|
command TEXT NOT NULL,
|
|
214
|
+
sql TEXT,
|
|
205
215
|
handle TEXT,
|
|
206
216
|
executed INTEGER NOT NULL,
|
|
207
217
|
cached INTEGER NOT NULL,
|
package/dist/src/stateql.js
CHANGED
|
@@ -613,7 +613,7 @@ export class StateQL {
|
|
|
613
613
|
finally {
|
|
614
614
|
await closeAdapterQuietly(adapter);
|
|
615
615
|
}
|
|
616
|
-
});
|
|
616
|
+
}, sql);
|
|
617
617
|
}
|
|
618
618
|
async show(idOrAlias) {
|
|
619
619
|
return this.withResult("show", idOrAlias, async (result) => ({
|
|
@@ -756,7 +756,7 @@ export class StateQL {
|
|
|
756
756
|
return this.run("exec", async (session) => {
|
|
757
757
|
const connection = this.requireConnection(session);
|
|
758
758
|
return this.performExec(session, connection, sql, options, this.executionContext(options));
|
|
759
|
-
});
|
|
759
|
+
}, sql);
|
|
760
760
|
}
|
|
761
761
|
async receipt(id) {
|
|
762
762
|
return this.run("receipt", async (session) => {
|
|
@@ -1023,9 +1023,10 @@ export class StateQL {
|
|
|
1023
1023
|
finally {
|
|
1024
1024
|
await closeAdapterQuietly(adapter);
|
|
1025
1025
|
}
|
|
1026
|
-
});
|
|
1026
|
+
}, sql);
|
|
1027
1027
|
}
|
|
1028
1028
|
async apply(planId, options = {}) {
|
|
1029
|
+
let historySql;
|
|
1029
1030
|
return this.run("apply", async (session) => {
|
|
1030
1031
|
this.rejectDuringStagedTransaction(session, "Plans");
|
|
1031
1032
|
const plan = this.store.getPlan(planId);
|
|
@@ -1043,6 +1044,7 @@ export class StateQL {
|
|
|
1043
1044
|
if (Date.parse(plan.expires_at) <= this.now().getTime()) {
|
|
1044
1045
|
throw new StateQLError("STALE_PLAN", "Plan has expired.");
|
|
1045
1046
|
}
|
|
1047
|
+
historySql = plan.sql;
|
|
1046
1048
|
const planParameters = parseJson(plan.parameters, `plan "${plan.id}" parameters`, isSqlParameters);
|
|
1047
1049
|
const claimToken = this.store.nextId("claim");
|
|
1048
1050
|
const claimed = this.store.claimPlan(plan.id, session.id, this.actorId, claimToken);
|
|
@@ -1096,7 +1098,7 @@ export class StateQL {
|
|
|
1096
1098
|
if (!retainClaim)
|
|
1097
1099
|
this.store.releasePlanClaim(plan.id, claimToken);
|
|
1098
1100
|
}
|
|
1099
|
-
});
|
|
1101
|
+
}, () => historySql);
|
|
1100
1102
|
}
|
|
1101
1103
|
async history(limit = 20) {
|
|
1102
1104
|
return this.run("history", async (session) => ({
|
|
@@ -1642,7 +1644,7 @@ export class StateQL {
|
|
|
1642
1644
|
result.state_version === stateVersion &&
|
|
1643
1645
|
result.state_signature === stateSignature);
|
|
1644
1646
|
}
|
|
1645
|
-
async run(command, action) {
|
|
1647
|
+
async run(command, action, historySql) {
|
|
1646
1648
|
const started = performance.now();
|
|
1647
1649
|
let session = this.store.ensureSession(this.sessionName);
|
|
1648
1650
|
const commandId = this.store.nextId("cmd");
|
|
@@ -1661,12 +1663,14 @@ export class StateQL {
|
|
|
1661
1663
|
try {
|
|
1662
1664
|
const result = await action(session);
|
|
1663
1665
|
const responseSession = result.session ?? session;
|
|
1666
|
+
const sqlText = resolveHistorySql(historySql);
|
|
1664
1667
|
this.store.addHistory({
|
|
1665
1668
|
id: commandId,
|
|
1666
1669
|
sessionId: session.id,
|
|
1667
1670
|
actorId: this.actorId,
|
|
1668
1671
|
command,
|
|
1669
1672
|
...(result.handle ? { handle: result.handle } : {}),
|
|
1673
|
+
...(sqlText !== undefined ? { sql: sqlText } : {}),
|
|
1670
1674
|
executed: result.executed ?? false,
|
|
1671
1675
|
cached: result.cached ?? false,
|
|
1672
1676
|
success: true,
|
|
@@ -1690,11 +1694,13 @@ export class StateQL {
|
|
|
1690
1694
|
}
|
|
1691
1695
|
catch (error) {
|
|
1692
1696
|
const stateqlError = asStateQLError(error);
|
|
1697
|
+
const sqlText = resolveHistorySql(historySql);
|
|
1693
1698
|
this.store.addHistory({
|
|
1694
1699
|
id: commandId,
|
|
1695
1700
|
sessionId: session.id,
|
|
1696
1701
|
actorId: this.actorId,
|
|
1697
1702
|
command,
|
|
1703
|
+
...(sqlText !== undefined ? { sql: sqlText } : {}),
|
|
1698
1704
|
executed: stateqlError.details.executed,
|
|
1699
1705
|
cached: false,
|
|
1700
1706
|
success: false,
|
|
@@ -1712,6 +1718,9 @@ export class StateQL {
|
|
|
1712
1718
|
}
|
|
1713
1719
|
}
|
|
1714
1720
|
}
|
|
1721
|
+
function resolveHistorySql(sql) {
|
|
1722
|
+
return typeof sql === "function" ? sql() : sql;
|
|
1723
|
+
}
|
|
1715
1724
|
function historyEntry(item) {
|
|
1716
1725
|
return {
|
|
1717
1726
|
command_id: item.id,
|
|
@@ -1719,6 +1728,7 @@ function historyEntry(item) {
|
|
|
1719
1728
|
session_id: item.session_id,
|
|
1720
1729
|
actor_id: item.actor_id,
|
|
1721
1730
|
command: item.command,
|
|
1731
|
+
sql: item.sql,
|
|
1722
1732
|
handle: item.handle,
|
|
1723
1733
|
executed: Boolean(item.executed),
|
|
1724
1734
|
cached: Boolean(item.cached),
|
package/dist/src/store.d.ts
CHANGED
|
@@ -98,6 +98,7 @@ export interface HistoryRecord {
|
|
|
98
98
|
session_id: string;
|
|
99
99
|
actor_id: string;
|
|
100
100
|
command: string;
|
|
101
|
+
sql: string | null;
|
|
101
102
|
handle: string | null;
|
|
102
103
|
executed: number;
|
|
103
104
|
cached: number;
|
|
@@ -267,6 +268,7 @@ export declare class StateStore {
|
|
|
267
268
|
sessionId: string;
|
|
268
269
|
actorId: string;
|
|
269
270
|
command: string;
|
|
271
|
+
sql?: string;
|
|
270
272
|
handle?: string;
|
|
271
273
|
executed: boolean;
|
|
272
274
|
cached: boolean;
|
package/dist/src/store.js
CHANGED
|
@@ -6,6 +6,7 @@ import { runMigrations } from "./migrations.js";
|
|
|
6
6
|
import { StateQLError } from "./errors.js";
|
|
7
7
|
import { isColumns, isRows, isSqlParameters, parseJson, toJsonSafe, } from "./util.js";
|
|
8
8
|
const HISTORY_LIMIT_PER_SESSION = 10_000;
|
|
9
|
+
const MAX_HISTORY_SQL_BYTES = 4_096;
|
|
9
10
|
const DEFAULT_MAX_STATE_BYTES = 256 * 1024 * 1024;
|
|
10
11
|
export class StateStore {
|
|
11
12
|
now;
|
|
@@ -791,10 +792,10 @@ export class StateStore {
|
|
|
791
792
|
const id = input.id ?? this.nextId("cmd");
|
|
792
793
|
this.db
|
|
793
794
|
.prepare(`INSERT INTO history
|
|
794
|
-
(id, timestamp, session_id, actor_id, command, handle, executed,
|
|
795
|
+
(id, timestamp, session_id, actor_id, command, sql, handle, executed,
|
|
795
796
|
cached, success, error_code)
|
|
796
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
797
|
-
.run(id, this.now().toISOString(), input.sessionId, input.actorId, input.command, input.handle ?? null, input.executed ? 1 : 0, input.cached ? 1 : 0, input.success ? 1 : 0, input.errorCode ?? null);
|
|
797
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
798
|
+
.run(id, this.now().toISOString(), input.sessionId, input.actorId, input.command, boundedHistorySql(input.sql), input.handle ?? null, input.executed ? 1 : 0, input.cached ? 1 : 0, input.success ? 1 : 0, input.errorCode ?? null);
|
|
798
799
|
this.db
|
|
799
800
|
.prepare(`DELETE FROM history
|
|
800
801
|
WHERE rowid IN (
|
|
@@ -1010,6 +1011,22 @@ export class StateStore {
|
|
|
1010
1011
|
}
|
|
1011
1012
|
}
|
|
1012
1013
|
}
|
|
1014
|
+
function boundedHistorySql(sql) {
|
|
1015
|
+
if (sql === undefined)
|
|
1016
|
+
return null;
|
|
1017
|
+
if (Buffer.byteLength(sql, "utf8") <= MAX_HISTORY_SQL_BYTES)
|
|
1018
|
+
return sql;
|
|
1019
|
+
const suffix = "…";
|
|
1020
|
+
let prefix = "";
|
|
1021
|
+
for (const character of sql) {
|
|
1022
|
+
if (Buffer.byteLength(`${prefix}${character}${suffix}`, "utf8") >
|
|
1023
|
+
MAX_HISTORY_SQL_BYTES) {
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
prefix += character;
|
|
1027
|
+
}
|
|
1028
|
+
return `${prefix}${suffix}`;
|
|
1029
|
+
}
|
|
1013
1030
|
function restrictMode(path, allowed) {
|
|
1014
1031
|
chmodSync(path, statSync(path).mode & allowed);
|
|
1015
1032
|
}
|
package/dist/src/types.d.ts
CHANGED