• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

snatalenko / node-cqrs / 22745360142

06 Mar 2026 01:50AM UTC coverage: 95.287% (+0.9%) from 94.396%
22745360142

Pull #28

github

web-flow
Merge 15ef847b4 into 828e39903
Pull Request #28: TypeScript and event dispatching pipeline refactoring

428 of 528 branches covered (81.06%)

1043 of 1091 new or added lines in 65 files covered. (95.6%)

3 existing lines in 2 files now uncovered.

1294 of 1358 relevant lines covered (95.29%)

31.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.36
/src/sqlite/SqliteObjectStorage.ts
1
import type { Statement, Database } from 'better-sqlite3';
2
import { guid } from './utils/index.ts';
5✔
3
import type { IContainer, IObjectStorage } from '../interfaces/index.ts';
4
import { AbstractSqliteAccessor } from './AbstractSqliteAccessor.ts';
5✔
5
import { assertFunction, assertString } from '../utils/assert.ts';
5✔
6

7
export class SqliteObjectStorage<TRecord> extends AbstractSqliteAccessor implements IObjectStorage<TRecord> {
5✔
8

9
        #tableName: string;
10
        #getQuery!: Statement<[Buffer], { data: string, version: number }>;
11
        #insertQuery!: Statement<[Buffer, string], void>;
12
        #updateByIdAndVersionQuery!: Statement<[string, Buffer, number], void>;
13
        #deleteQuery!: Statement<[Buffer], void>;
14

15
        constructor(o: Pick<IContainer, 'viewModelSqliteDb' | 'viewModelSqliteDbFactory'> & {
16
                tableName: string
17
        }) {
18
                super(o);
36✔
19

20
                this.#tableName = o.tableName;
36✔
21
        }
22

23
        protected initialize(db: Database) {
24
                db.exec(`CREATE TABLE IF NOT EXISTS ${this.#tableName} (
22✔
25
                        id BLOB PRIMARY KEY,
26
                        version INTEGER DEFAULT 1,
27
                        data TEXT NOT NULL
28
                );`);
29

30
                this.#getQuery = db.prepare(`
22✔
31
                        SELECT data, version
32
                        FROM ${this.#tableName}
33
                        WHERE id = ?
34
                `);
35

36
                this.#insertQuery = db.prepare(`
22✔
37
                        INSERT INTO ${this.#tableName} (id, data)
38
                        VALUES (?, ?)
39
                `);
40

41
                this.#updateByIdAndVersionQuery = db.prepare(`
22✔
42
                        UPDATE ${this.#tableName}
43
                        SET
44
                                data = ?,
45
                                version = version + 1
46
                        WHERE
47
                                id = ?
48
                                AND version = ?
49
                `);
50

51
                this.#deleteQuery = db.prepare(`
22✔
52
                        DELETE FROM ${this.#tableName}
53
                        WHERE id = ?
54
                `);
55
        }
56

57
        async get(id: string): Promise<TRecord | undefined> {
58
                assertString(id, 'id');
18✔
59

60
                await this.assertConnection();
17✔
61

62
                const r = this.#getQuery.get(guid(id));
17✔
63
                if (!r)
17✔
64
                        return undefined;
6✔
65

66
                return JSON.parse(r.data);
11✔
67
        }
68

69
        getSync(id: string): TRecord | undefined {
70
                assertString(id, 'id');
2✔
71

72
                const r = this.#getQuery.get(guid(id));
2✔
73
                if (!r)
2✔
74
                        return undefined;
1✔
75

76
                return JSON.parse(r.data);
1✔
77
        }
78

79
        async create(id: string, data: TRecord) {
80
                assertString(id, 'id');
11✔
81

82
                await this.assertConnection();
11✔
83

84
                this.#createSync(id, data);
11✔
85
        }
86

87
        #createSync(id: string, data: TRecord) {
88
                const r = this.#insertQuery.run(guid(id), JSON.stringify(data));
14✔
89
                if (r.changes !== 1)
13!
NEW
90
                        throw new Error(`Record '${id}' could not be created`);
×
91
        }
92

93
        async update(id: string, update: (r: TRecord) => TRecord) {
94
                assertString(id, 'id');
4✔
95
                assertFunction(update, 'update');
4✔
96

97
                await this.assertConnection();
4✔
98

99
                this.#updateSync(id, update);
4✔
100
        }
101

102
        #updateSync(id: string, update: (r: TRecord) => TRecord) {
103
                const gid = guid(id);
4✔
104
                const record = this.#getQuery.get(gid);
4✔
105
                if (!record)
4✔
106
                        throw new Error(`Record '${id}' does not exist`);
2✔
107

108
                this.#updateExistingSync(id, record, update);
2✔
109
        }
110

111
        #updateExistingSync(id: string, record: { data: string, version: number }, update: (r: TRecord) => TRecord) {
112
                const gid = guid(id);
53✔
113
                const data = JSON.parse(record.data);
53✔
114
                const updatedData = update(data);
53✔
115
                const updatedJson = JSON.stringify(updatedData);
53✔
116

117
                // Version check is implemented to ensure the record isn't modified by another process.
118
                // A conflict resolution strategy could potentially be passed as an option to this method,
119
                // but for now, conflict resolution should happen outside this class.
120
                const r = this.#updateByIdAndVersionQuery.run(updatedJson, gid, record.version);
53✔
121
                if (r.changes !== 1)
53!
NEW
122
                        throw new Error(`Record '${id}' could not be updated`);
×
123
        }
124

125
        async updateEnforcingNew(id: string, update: (r?: TRecord) => TRecord) {
126
                assertString(id, 'id');
54✔
127
                assertFunction(update, 'update');
54✔
128

129
                await this.assertConnection();
54✔
130

131
                const record = this.#getQuery.get(guid(id));
54✔
132
                if (record)
54✔
133
                        this.#updateExistingSync(id, record, update as (r: TRecord) => TRecord);
51✔
134
                else
135
                        this.#createSync(id, update());
3✔
136
        }
137

138
        async delete(id: string): Promise<boolean> {
139
                assertString(id, 'id');
4✔
140

141
                await this.assertConnection();
4✔
142

143
                const r = this.#deleteQuery.run(guid(id));
4✔
144
                return r.changes === 1;
4✔
145
        }
146
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc