@alstate/sqlite 0.1.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/LICENSE +21 -0
- package/README.md +15 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations.d.ts +3 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +96 -0
- package/dist/migrations.js.map +1 -0
- package/dist/sqlite-learning-store.d.ts +26 -0
- package/dist/sqlite-learning-store.d.ts.map +1 -0
- package/dist/sqlite-learning-store.js +390 -0
- package/dist/sqlite-learning-store.js.map +1 -0
- package/package.json +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alstate contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# `@alstate/sqlite`
|
|
2
|
+
|
|
3
|
+
Experimental SQLite persistence adapter for `@alstate/core`, implemented with
|
|
4
|
+
Node.js `node:sqlite`.
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
import { SqliteLearningStore } from "@alstate/sqlite";
|
|
8
|
+
|
|
9
|
+
const store = new SqliteLearningStore("learning.db");
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Requires Node.js 22.13 or later. The adapter applies schema migrations on open,
|
|
13
|
+
uses transactions for composite writes and rejects stale review revisions.
|
|
14
|
+
|
|
15
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmEhD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAkC5D"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
const migrations = [
|
|
2
|
+
{
|
|
3
|
+
version: 1,
|
|
4
|
+
name: "learning_engine_schema",
|
|
5
|
+
sql: `
|
|
6
|
+
CREATE TABLE engine_items (
|
|
7
|
+
id INTEGER PRIMARY KEY,
|
|
8
|
+
data_json TEXT NOT NULL CHECK (json_valid(data_json))
|
|
9
|
+
) STRICT;
|
|
10
|
+
|
|
11
|
+
CREATE TABLE engine_algorithms (
|
|
12
|
+
id INTEGER PRIMARY KEY,
|
|
13
|
+
name TEXT NOT NULL UNIQUE CHECK (length(trim(name)) > 0),
|
|
14
|
+
description TEXT,
|
|
15
|
+
version TEXT NOT NULL CHECK (length(trim(version)) > 0),
|
|
16
|
+
config_json TEXT NOT NULL CHECK (json_valid(config_json))
|
|
17
|
+
) STRICT;
|
|
18
|
+
|
|
19
|
+
CREATE TABLE engine_states (
|
|
20
|
+
id INTEGER PRIMARY KEY,
|
|
21
|
+
learning_item_id INTEGER NOT NULL,
|
|
22
|
+
algorithm_id INTEGER NOT NULL,
|
|
23
|
+
due_at TEXT NOT NULL,
|
|
24
|
+
state_json TEXT NOT NULL CHECK (json_valid(state_json)),
|
|
25
|
+
UNIQUE (learning_item_id, algorithm_id),
|
|
26
|
+
FOREIGN KEY (learning_item_id)
|
|
27
|
+
REFERENCES engine_items (id) ON DELETE CASCADE,
|
|
28
|
+
FOREIGN KEY (algorithm_id)
|
|
29
|
+
REFERENCES engine_algorithms (id) ON DELETE RESTRICT
|
|
30
|
+
) STRICT;
|
|
31
|
+
|
|
32
|
+
CREATE INDEX engine_states_due_idx
|
|
33
|
+
ON engine_states (algorithm_id, due_at, learning_item_id);
|
|
34
|
+
|
|
35
|
+
CREATE TABLE engine_reviews (
|
|
36
|
+
id INTEGER PRIMARY KEY,
|
|
37
|
+
learning_item_id INTEGER NOT NULL,
|
|
38
|
+
algorithm_id INTEGER NOT NULL,
|
|
39
|
+
rating TEXT NOT NULL CHECK (length(trim(rating)) > 0),
|
|
40
|
+
review_json TEXT NOT NULL CHECK (json_valid(review_json)),
|
|
41
|
+
response_time_ms INTEGER CHECK (
|
|
42
|
+
response_time_ms IS NULL OR response_time_ms >= 0
|
|
43
|
+
),
|
|
44
|
+
reviewed_at TEXT NOT NULL,
|
|
45
|
+
FOREIGN KEY (learning_item_id)
|
|
46
|
+
REFERENCES engine_items (id) ON DELETE CASCADE,
|
|
47
|
+
FOREIGN KEY (algorithm_id)
|
|
48
|
+
REFERENCES engine_algorithms (id) ON DELETE RESTRICT
|
|
49
|
+
) STRICT;
|
|
50
|
+
|
|
51
|
+
CREATE INDEX engine_reviews_item_time_idx
|
|
52
|
+
ON engine_reviews (learning_item_id, reviewed_at DESC, id DESC);
|
|
53
|
+
`,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
version: 2,
|
|
57
|
+
name: "optimistic_review_concurrency",
|
|
58
|
+
sql: `
|
|
59
|
+
ALTER TABLE engine_states
|
|
60
|
+
ADD COLUMN revision INTEGER NOT NULL DEFAULT 0
|
|
61
|
+
CHECK (revision >= 0);
|
|
62
|
+
`,
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
export function migrateDatabase(database) {
|
|
66
|
+
database.exec(`
|
|
67
|
+
CREATE TABLE IF NOT EXISTS engine_schema_migrations (
|
|
68
|
+
version INTEGER PRIMARY KEY,
|
|
69
|
+
name TEXT NOT NULL UNIQUE,
|
|
70
|
+
applied_at TEXT NOT NULL
|
|
71
|
+
) STRICT;
|
|
72
|
+
`);
|
|
73
|
+
const applied = new Set(database
|
|
74
|
+
.prepare("SELECT version FROM engine_schema_migrations")
|
|
75
|
+
.all().map((row) => row.version));
|
|
76
|
+
const record = database.prepare(`
|
|
77
|
+
INSERT INTO engine_schema_migrations (version, name, applied_at)
|
|
78
|
+
VALUES (?, ?, ?)
|
|
79
|
+
`);
|
|
80
|
+
for (const migration of migrations) {
|
|
81
|
+
if (applied.has(migration.version)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
database.exec("BEGIN IMMEDIATE");
|
|
85
|
+
try {
|
|
86
|
+
database.exec(migration.sql);
|
|
87
|
+
record.run(migration.version, migration.name, new Date().toISOString());
|
|
88
|
+
database.exec("COMMIT");
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
database.exec("ROLLBACK");
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG;IACjB;QACE,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,wBAAwB;QAC9B,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgDJ;KACF;IACD;QACE,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,+BAA+B;QACrC,GAAG,EAAE;;;;KAIJ;KACF;CACO,CAAC;AAEX,MAAM,UAAU,eAAe,CAAC,QAAsB;IACpD,QAAQ,CAAC,IAAI,CAAC;;;;;;GAMb,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAEnB,QAAQ;SACL,OAAO,CAAC,8CAA8C,CAAC;SACvD,GAAG,EACP,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAC5B,CAAC;IACF,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC;;;GAG/B,CAAC,CAAC;IAEH,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,SAAS;QACX,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACjC,IAAI,CAAC;YACH,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;YACxE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC1B,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AlgorithmRegistration, DueStoredItem, LearningStore, NewItemWithState, RegisteredAlgorithm, StateUpdate, NewReviewRecord } from "@alstate/core";
|
|
2
|
+
import { type AlgorithmId, type JsonObject, type LearningItem, type LearningItemId, type LearningState, type PageQuery, type ReviewRecord } from "@alstate/core";
|
|
3
|
+
export declare class SqliteLearningStore implements LearningStore {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(path?: string);
|
|
6
|
+
registerAlgorithm(registration: AlgorithmRegistration): Promise<RegisteredAlgorithm>;
|
|
7
|
+
createItem(input: NewItemWithState): Promise<LearningItem>;
|
|
8
|
+
findItem(id: LearningItemId, registeredAlgorithmId: AlgorithmId): Promise<LearningItem | null>;
|
|
9
|
+
listItems(registeredAlgorithmId: AlgorithmId, query?: PageQuery): Promise<readonly LearningItem[]>;
|
|
10
|
+
updateItem(id: LearningItemId, registeredAlgorithmId: AlgorithmId, data: JsonObject): Promise<LearningItem | null>;
|
|
11
|
+
deleteItem(id: LearningItemId, registeredAlgorithmId: AlgorithmId): Promise<boolean>;
|
|
12
|
+
findState(itemId: LearningItemId, registeredAlgorithmId: AlgorithmId): Promise<LearningState | null>;
|
|
13
|
+
listDue(input: {
|
|
14
|
+
readonly algorithmId: AlgorithmId;
|
|
15
|
+
readonly dueAtOrBefore: Date;
|
|
16
|
+
readonly limit?: number;
|
|
17
|
+
}): Promise<readonly DueStoredItem[]>;
|
|
18
|
+
commitReview(input: {
|
|
19
|
+
readonly state: StateUpdate;
|
|
20
|
+
readonly review: NewReviewRecord;
|
|
21
|
+
}): Promise<ReviewRecord>;
|
|
22
|
+
listReviews(itemId: LearningItemId, registeredAlgorithmId: AlgorithmId, query?: PageQuery): Promise<readonly ReviewRecord[]>;
|
|
23
|
+
close(): void;
|
|
24
|
+
private transaction;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=sqlite-learning-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-learning-store.d.ts","sourceRoot":"","sources":["../src/sqlite-learning-store.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAKL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAKvB,qBAAa,mBAAoB,YAAW,aAAa;;IAGvD,YAAmB,IAAI,GAAE,MAAmB,EAU3C;IAEY,iBAAiB,CAC5B,YAAY,EAAE,qBAAqB,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAuC9B;IAEY,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBtE;IAEY,QAAQ,CACnB,EAAE,EAAE,cAAc,EAClB,qBAAqB,EAAE,WAAW,GACjC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAU9B;IAEY,SAAS,CACpB,qBAAqB,EAAE,WAAW,EAClC,KAAK,GAAE,SAAc,GACpB,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC,CAsBlC;IAEY,UAAU,CACrB,EAAE,EAAE,cAAc,EAClB,qBAAqB,EAAE,WAAW,EAClC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAc9B;IAEY,UAAU,CACrB,EAAE,EAAE,cAAc,EAClB,qBAAqB,EAAE,WAAW,GACjC,OAAO,CAAC,OAAO,CAAC,CAYlB;IAEY,SAAS,CACpB,MAAM,EAAE,cAAc,EACtB,qBAAqB,EAAE,WAAW,GACjC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAS/B;IAEY,OAAO,CAAC,KAAK,EAAE;QAC1B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;QAClC,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC;QAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAyCpC;IAEY,YAAY,CAAC,KAAK,EAAE;QAC/B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;QAC5B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;KAClC,GAAG,OAAO,CAAC,YAAY,CAAC,CA+CxB;IAEY,WAAW,CACtB,MAAM,EAAE,cAAc,EACtB,qBAAqB,EAAE,WAAW,EAClC,KAAK,GAAE,SAAc,GACpB,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC,CAuBlC;IAEM,KAAK,IAAI,IAAI,CAEnB;IAED,OAAO,CAAC,WAAW;CAWpB"}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { mkdirSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { DatabaseSync, } from "node:sqlite";
|
|
4
|
+
import { AlgorithmMismatchError, ConcurrentReviewError, } from "@alstate/core";
|
|
5
|
+
import { algorithmId, learningItemId, learningStateId, reviewRecordId, } from "@alstate/core";
|
|
6
|
+
import { migrateDatabase } from "./migrations.js";
|
|
7
|
+
export class SqliteLearningStore {
|
|
8
|
+
#database;
|
|
9
|
+
constructor(path = ":memory:") {
|
|
10
|
+
if (path !== ":memory:") {
|
|
11
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
this.#database = new DatabaseSync(path, {
|
|
14
|
+
enableForeignKeyConstraints: true,
|
|
15
|
+
enableDoubleQuotedStringLiterals: false,
|
|
16
|
+
});
|
|
17
|
+
this.#database.exec("PRAGMA busy_timeout = 5000");
|
|
18
|
+
migrateDatabase(this.#database);
|
|
19
|
+
}
|
|
20
|
+
async registerAlgorithm(registration) {
|
|
21
|
+
requireNonBlank(registration.name, "algorithm name");
|
|
22
|
+
requireNonBlank(registration.version, "algorithm version");
|
|
23
|
+
const existing = this.#database
|
|
24
|
+
.prepare(`
|
|
25
|
+
SELECT id, name, version, description, config_json
|
|
26
|
+
FROM engine_algorithms
|
|
27
|
+
WHERE name = ?
|
|
28
|
+
`)
|
|
29
|
+
.get(registration.name);
|
|
30
|
+
if (existing !== undefined) {
|
|
31
|
+
const stored = mapAlgorithm(existing);
|
|
32
|
+
if (stored.version !== registration.version ||
|
|
33
|
+
canonicalJson(stored.configuration) !==
|
|
34
|
+
canonicalJson(registration.configuration)) {
|
|
35
|
+
throw new AlgorithmMismatchError(registration.name);
|
|
36
|
+
}
|
|
37
|
+
return stored;
|
|
38
|
+
}
|
|
39
|
+
const result = this.#database
|
|
40
|
+
.prepare(`
|
|
41
|
+
INSERT INTO engine_algorithms
|
|
42
|
+
(name, version, description, config_json)
|
|
43
|
+
VALUES (?, ?, ?, ?)
|
|
44
|
+
`)
|
|
45
|
+
.run(registration.name, registration.version, registration.description ?? null, JSON.stringify(registration.configuration));
|
|
46
|
+
return Object.freeze({
|
|
47
|
+
id: algorithmId(toSafeInteger(result.lastInsertRowid)),
|
|
48
|
+
...registration,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async createItem(input) {
|
|
52
|
+
return this.transaction(() => {
|
|
53
|
+
const itemResult = this.#database
|
|
54
|
+
.prepare("INSERT INTO engine_items (data_json) VALUES (?)")
|
|
55
|
+
.run(JSON.stringify(input.data));
|
|
56
|
+
const id = learningItemId(toSafeInteger(itemResult.lastInsertRowid));
|
|
57
|
+
this.#database
|
|
58
|
+
.prepare(`
|
|
59
|
+
INSERT INTO engine_states
|
|
60
|
+
(learning_item_id, algorithm_id, due_at, state_json)
|
|
61
|
+
VALUES (?, ?, ?, ?)
|
|
62
|
+
`)
|
|
63
|
+
.run(id, input.algorithmId, isoDate(input.dueAt, "initial due time"), JSON.stringify(input.stateData));
|
|
64
|
+
return freezeItem({ id, data: input.data });
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async findItem(id, registeredAlgorithmId) {
|
|
68
|
+
const row = this.#database
|
|
69
|
+
.prepare(`
|
|
70
|
+
SELECT item.id, item.data_json
|
|
71
|
+
FROM engine_items item
|
|
72
|
+
JOIN engine_states state ON state.learning_item_id = item.id
|
|
73
|
+
WHERE item.id = ? AND state.algorithm_id = ?
|
|
74
|
+
`)
|
|
75
|
+
.get(id, registeredAlgorithmId);
|
|
76
|
+
return row === undefined ? null : mapItem(row);
|
|
77
|
+
}
|
|
78
|
+
async listItems(registeredAlgorithmId, query = {}) {
|
|
79
|
+
validatePage(query);
|
|
80
|
+
const parameters = [registeredAlgorithmId];
|
|
81
|
+
let sql = `
|
|
82
|
+
SELECT item.id, item.data_json
|
|
83
|
+
FROM engine_items item
|
|
84
|
+
JOIN engine_states state ON state.learning_item_id = item.id
|
|
85
|
+
WHERE state.algorithm_id = ?
|
|
86
|
+
ORDER BY item.id
|
|
87
|
+
`;
|
|
88
|
+
if (query.limit !== undefined) {
|
|
89
|
+
sql += " LIMIT ?";
|
|
90
|
+
parameters.push(query.limit);
|
|
91
|
+
}
|
|
92
|
+
else if (query.offset !== undefined) {
|
|
93
|
+
sql += " LIMIT -1";
|
|
94
|
+
}
|
|
95
|
+
if (query.offset !== undefined) {
|
|
96
|
+
sql += " OFFSET ?";
|
|
97
|
+
parameters.push(query.offset);
|
|
98
|
+
}
|
|
99
|
+
const rows = this.#database.prepare(sql).all(...parameters);
|
|
100
|
+
return Object.freeze(rows.map(mapItem));
|
|
101
|
+
}
|
|
102
|
+
async updateItem(id, registeredAlgorithmId, data) {
|
|
103
|
+
const result = this.#database
|
|
104
|
+
.prepare(`
|
|
105
|
+
UPDATE engine_items SET data_json = ?
|
|
106
|
+
WHERE id = ? AND EXISTS (
|
|
107
|
+
SELECT 1 FROM engine_states state
|
|
108
|
+
WHERE state.learning_item_id = engine_items.id
|
|
109
|
+
AND state.algorithm_id = ?
|
|
110
|
+
)
|
|
111
|
+
`)
|
|
112
|
+
.run(JSON.stringify(data), id, registeredAlgorithmId);
|
|
113
|
+
return toSafeInteger(result.changes) === 0
|
|
114
|
+
? null
|
|
115
|
+
: freezeItem({ id, data });
|
|
116
|
+
}
|
|
117
|
+
async deleteItem(id, registeredAlgorithmId) {
|
|
118
|
+
const result = this.#database
|
|
119
|
+
.prepare(`
|
|
120
|
+
DELETE FROM engine_items
|
|
121
|
+
WHERE id = ? AND EXISTS (
|
|
122
|
+
SELECT 1 FROM engine_states state
|
|
123
|
+
WHERE state.learning_item_id = engine_items.id
|
|
124
|
+
AND state.algorithm_id = ?
|
|
125
|
+
)
|
|
126
|
+
`)
|
|
127
|
+
.run(id, registeredAlgorithmId);
|
|
128
|
+
return toSafeInteger(result.changes) > 0;
|
|
129
|
+
}
|
|
130
|
+
async findState(itemId, registeredAlgorithmId) {
|
|
131
|
+
const row = this.#database
|
|
132
|
+
.prepare(`
|
|
133
|
+
SELECT id, learning_item_id, algorithm_id, revision, due_at, state_json
|
|
134
|
+
FROM engine_states
|
|
135
|
+
WHERE learning_item_id = ? AND algorithm_id = ?
|
|
136
|
+
`)
|
|
137
|
+
.get(itemId, registeredAlgorithmId);
|
|
138
|
+
return row === undefined ? null : mapState(row);
|
|
139
|
+
}
|
|
140
|
+
async listDue(input) {
|
|
141
|
+
validateLimit(input.limit);
|
|
142
|
+
const parameters = [
|
|
143
|
+
input.algorithmId,
|
|
144
|
+
isoDate(input.dueAtOrBefore, "due query time"),
|
|
145
|
+
];
|
|
146
|
+
let sql = `
|
|
147
|
+
SELECT
|
|
148
|
+
item.id AS item_id,
|
|
149
|
+
item.data_json,
|
|
150
|
+
state.id AS state_id,
|
|
151
|
+
state.algorithm_id,
|
|
152
|
+
state.revision,
|
|
153
|
+
state.due_at,
|
|
154
|
+
state.state_json
|
|
155
|
+
FROM engine_states state
|
|
156
|
+
JOIN engine_items item ON item.id = state.learning_item_id
|
|
157
|
+
WHERE state.algorithm_id = ? AND state.due_at <= ?
|
|
158
|
+
ORDER BY state.due_at, item.id
|
|
159
|
+
`;
|
|
160
|
+
if (input.limit !== undefined) {
|
|
161
|
+
sql += " LIMIT ?";
|
|
162
|
+
parameters.push(input.limit);
|
|
163
|
+
}
|
|
164
|
+
const rows = this.#database.prepare(sql).all(...parameters);
|
|
165
|
+
return Object.freeze(rows.map((row) => {
|
|
166
|
+
const id = learningItemId(requireNumber(row, "item_id"));
|
|
167
|
+
return Object.freeze({
|
|
168
|
+
item: freezeItem({ id, data: parseObject(row, "data_json") }),
|
|
169
|
+
state: freezeState({
|
|
170
|
+
id: learningStateId(requireNumber(row, "state_id")),
|
|
171
|
+
learningItemId: id,
|
|
172
|
+
algorithmId: algorithmId(requireNumber(row, "algorithm_id")),
|
|
173
|
+
revision: requireNumber(row, "revision"),
|
|
174
|
+
dueAt: new Date(requireString(row, "due_at")),
|
|
175
|
+
data: parseObject(row, "state_json"),
|
|
176
|
+
}),
|
|
177
|
+
});
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
async commitReview(input) {
|
|
181
|
+
return this.transaction(() => {
|
|
182
|
+
if (input.state.state.learningItemId !== input.review.learningItemId ||
|
|
183
|
+
input.state.state.algorithmId !== input.review.algorithmId) {
|
|
184
|
+
throw new TypeError("Review identity must match the state being updated.");
|
|
185
|
+
}
|
|
186
|
+
const update = this.#database
|
|
187
|
+
.prepare(`
|
|
188
|
+
UPDATE engine_states
|
|
189
|
+
SET due_at = ?, state_json = ?, revision = revision + 1
|
|
190
|
+
WHERE id = ? AND revision = ?
|
|
191
|
+
`)
|
|
192
|
+
.run(isoDate(input.state.dueAt, "next due time"), JSON.stringify(input.state.data), input.state.state.id, input.state.state.revision);
|
|
193
|
+
if (toSafeInteger(update.changes) !== 1) {
|
|
194
|
+
throw new ConcurrentReviewError(input.review.learningItemId);
|
|
195
|
+
}
|
|
196
|
+
const review = input.review;
|
|
197
|
+
validateResponseTime(review.responseTimeMs);
|
|
198
|
+
const result = this.#database
|
|
199
|
+
.prepare(`
|
|
200
|
+
INSERT INTO engine_reviews
|
|
201
|
+
(
|
|
202
|
+
learning_item_id, algorithm_id, rating, review_json,
|
|
203
|
+
response_time_ms, reviewed_at
|
|
204
|
+
)
|
|
205
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
206
|
+
`)
|
|
207
|
+
.run(review.learningItemId, review.algorithmId, requireNonBlank(review.rating, "rating"), JSON.stringify(review.data), review.responseTimeMs ?? null, isoDate(review.reviewedAt, "review time"));
|
|
208
|
+
return freezeReview({
|
|
209
|
+
id: reviewRecordId(toSafeInteger(result.lastInsertRowid)),
|
|
210
|
+
...review,
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
async listReviews(itemId, registeredAlgorithmId, query = {}) {
|
|
215
|
+
validatePage(query);
|
|
216
|
+
const parameters = [itemId, registeredAlgorithmId];
|
|
217
|
+
let sql = `
|
|
218
|
+
SELECT
|
|
219
|
+
id, learning_item_id, algorithm_id, rating, review_json,
|
|
220
|
+
response_time_ms, reviewed_at
|
|
221
|
+
FROM engine_reviews
|
|
222
|
+
WHERE learning_item_id = ? AND algorithm_id = ?
|
|
223
|
+
ORDER BY reviewed_at DESC, id DESC
|
|
224
|
+
`;
|
|
225
|
+
if (query.limit !== undefined) {
|
|
226
|
+
sql += " LIMIT ?";
|
|
227
|
+
parameters.push(query.limit);
|
|
228
|
+
}
|
|
229
|
+
else if (query.offset !== undefined) {
|
|
230
|
+
sql += " LIMIT -1";
|
|
231
|
+
}
|
|
232
|
+
if (query.offset !== undefined) {
|
|
233
|
+
sql += " OFFSET ?";
|
|
234
|
+
parameters.push(query.offset);
|
|
235
|
+
}
|
|
236
|
+
const rows = this.#database.prepare(sql).all(...parameters);
|
|
237
|
+
return Object.freeze(rows.map(mapReview));
|
|
238
|
+
}
|
|
239
|
+
close() {
|
|
240
|
+
this.#database.close();
|
|
241
|
+
}
|
|
242
|
+
transaction(work) {
|
|
243
|
+
this.#database.exec("BEGIN IMMEDIATE");
|
|
244
|
+
try {
|
|
245
|
+
const result = work();
|
|
246
|
+
this.#database.exec("COMMIT");
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
this.#database.exec("ROLLBACK");
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function mapAlgorithm(row) {
|
|
256
|
+
const description = row["description"];
|
|
257
|
+
return Object.freeze({
|
|
258
|
+
id: algorithmId(requireNumber(row, "id")),
|
|
259
|
+
name: requireString(row, "name"),
|
|
260
|
+
version: requireString(row, "version"),
|
|
261
|
+
...(description === null
|
|
262
|
+
? {}
|
|
263
|
+
: { description: requireString(row, "description") }),
|
|
264
|
+
configuration: parseObject(row, "config_json"),
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
function mapItem(row) {
|
|
268
|
+
return freezeItem({
|
|
269
|
+
id: learningItemId(requireNumber(row, "id")),
|
|
270
|
+
data: parseObject(row, "data_json"),
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function mapState(row) {
|
|
274
|
+
return freezeState({
|
|
275
|
+
id: learningStateId(requireNumber(row, "id")),
|
|
276
|
+
learningItemId: learningItemId(requireNumber(row, "learning_item_id")),
|
|
277
|
+
algorithmId: algorithmId(requireNumber(row, "algorithm_id")),
|
|
278
|
+
revision: requireNumber(row, "revision"),
|
|
279
|
+
dueAt: new Date(requireString(row, "due_at")),
|
|
280
|
+
data: parseObject(row, "state_json"),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
function mapReview(row) {
|
|
284
|
+
const responseTime = row["response_time_ms"];
|
|
285
|
+
return freezeReview({
|
|
286
|
+
id: reviewRecordId(requireNumber(row, "id")),
|
|
287
|
+
learningItemId: learningItemId(requireNumber(row, "learning_item_id")),
|
|
288
|
+
algorithmId: algorithmId(requireNumber(row, "algorithm_id")),
|
|
289
|
+
rating: requireString(row, "rating"),
|
|
290
|
+
data: parseObject(row, "review_json"),
|
|
291
|
+
reviewedAt: new Date(requireString(row, "reviewed_at")),
|
|
292
|
+
...(responseTime === null
|
|
293
|
+
? {}
|
|
294
|
+
: { responseTimeMs: requireNumber(row, "response_time_ms") }),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
function freezeItem(item) {
|
|
298
|
+
return Object.freeze({ ...item, data: Object.freeze({ ...item.data }) });
|
|
299
|
+
}
|
|
300
|
+
function freezeState(state) {
|
|
301
|
+
const dueAt = validDate(state.dueAt, "stored due time");
|
|
302
|
+
return Object.freeze({
|
|
303
|
+
...state,
|
|
304
|
+
dueAt,
|
|
305
|
+
data: Object.freeze({ ...state.data }),
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
function freezeReview(record) {
|
|
309
|
+
const reviewedAt = validDate(record.reviewedAt, "stored review time");
|
|
310
|
+
return Object.freeze({
|
|
311
|
+
...record,
|
|
312
|
+
reviewedAt,
|
|
313
|
+
data: Object.freeze({ ...record.data }),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function parseObject(row, column) {
|
|
317
|
+
const value = JSON.parse(requireString(row, column));
|
|
318
|
+
if (value === null || Array.isArray(value) || typeof value !== "object") {
|
|
319
|
+
throw new TypeError(`Database column '${column}' must contain an object.`);
|
|
320
|
+
}
|
|
321
|
+
return value;
|
|
322
|
+
}
|
|
323
|
+
function requireNumber(row, column) {
|
|
324
|
+
const value = row[column];
|
|
325
|
+
if (typeof value !== "number") {
|
|
326
|
+
throw new TypeError(`Database column '${column}' must be a number.`);
|
|
327
|
+
}
|
|
328
|
+
return value;
|
|
329
|
+
}
|
|
330
|
+
function requireString(row, column) {
|
|
331
|
+
const value = row[column];
|
|
332
|
+
if (typeof value !== "string") {
|
|
333
|
+
throw new TypeError(`Database column '${column}' must be a string.`);
|
|
334
|
+
}
|
|
335
|
+
return value;
|
|
336
|
+
}
|
|
337
|
+
function toSafeInteger(value) {
|
|
338
|
+
const number = typeof value === "bigint" ? Number(value) : value;
|
|
339
|
+
if (!Number.isSafeInteger(number)) {
|
|
340
|
+
throw new TypeError("SQLite returned an unsafe integer.");
|
|
341
|
+
}
|
|
342
|
+
return number;
|
|
343
|
+
}
|
|
344
|
+
function requireNonBlank(value, field) {
|
|
345
|
+
if (value.trim().length === 0) {
|
|
346
|
+
throw new TypeError(`${field} must not be blank.`);
|
|
347
|
+
}
|
|
348
|
+
return value;
|
|
349
|
+
}
|
|
350
|
+
function validDate(value, field) {
|
|
351
|
+
if (Number.isNaN(value.getTime())) {
|
|
352
|
+
throw new TypeError(`${field} must be a valid date.`);
|
|
353
|
+
}
|
|
354
|
+
return new Date(value);
|
|
355
|
+
}
|
|
356
|
+
function isoDate(value, field) {
|
|
357
|
+
return validDate(value, field).toISOString();
|
|
358
|
+
}
|
|
359
|
+
function validatePage(query) {
|
|
360
|
+
validateLimit(query.limit);
|
|
361
|
+
if (query.offset !== undefined &&
|
|
362
|
+
(!Number.isSafeInteger(query.offset) || query.offset < 0)) {
|
|
363
|
+
throw new TypeError("offset must be a non-negative safe integer.");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function validateLimit(limit) {
|
|
367
|
+
if (limit !== undefined && (!Number.isSafeInteger(limit) || limit < 0)) {
|
|
368
|
+
throw new TypeError("limit must be a non-negative safe integer.");
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function validateResponseTime(value) {
|
|
372
|
+
if (value !== undefined && (!Number.isFinite(value) || value < 0)) {
|
|
373
|
+
throw new TypeError("responseTimeMs must be a non-negative number.");
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
function canonicalJson(value) {
|
|
377
|
+
return JSON.stringify(sortJson(value));
|
|
378
|
+
}
|
|
379
|
+
function sortJson(value) {
|
|
380
|
+
if (Array.isArray(value)) {
|
|
381
|
+
return value.map(sortJson);
|
|
382
|
+
}
|
|
383
|
+
if (value !== null && typeof value === "object") {
|
|
384
|
+
return Object.fromEntries(Object.entries(value)
|
|
385
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
386
|
+
.map(([key, entry]) => [key, sortJson(entry)]));
|
|
387
|
+
}
|
|
388
|
+
return value;
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=sqlite-learning-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-learning-store.js","sourceRoot":"","sources":["../src/sqlite-learning-store.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alstate/sqlite",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SQLite persistence adapter for Alstate.",
|
|
5
|
+
"keywords": ["learning", "scheduling", "sqlite", "spaced-repetition"],
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc --project tsconfig.build.json",
|
|
19
|
+
"clean": "node --eval \"require('node:fs').rmSync('dist', { recursive: true, force: true }); require('node:fs').rmSync('.test-dist', { recursive: true, force: true })\"",
|
|
20
|
+
"test": "tsc --project tsconfig.test.json && node --test \".test-dist/test/**/*.test.js\"",
|
|
21
|
+
"typecheck": "tsc --project tsconfig.json --noEmit"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": { "@alstate/core": "0.1.0" },
|
|
24
|
+
"engines": { "node": ">=22.13.0" },
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/laiqfun/alstate.git",
|
|
29
|
+
"directory": "packages/sqlite"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/laiqfun/alstate#readme",
|
|
32
|
+
"bugs": { "url": "https://github.com/laiqfun/alstate/issues" },
|
|
33
|
+
"publishConfig": { "access": "public" }
|
|
34
|
+
}
|