@hexaijs/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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Sangwoo Hyun
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,248 @@
1
+ # @hexaijs/sqlite
2
+
3
+ > SQLite transaction management for testing and lightweight use cases
4
+
5
+ ## Overview
6
+
7
+ `@hexaijs/sqlite` provides an SQLite implementation of the `UnitOfWork` interface from `@hexaijs/core`. It enables transaction management against SQLite databases, making it particularly useful for fast, isolated integration tests.
8
+
9
+ The package centers around `SqliteUnitOfWork`, which wraps operations in SQLite transactions. Unlike `PostgresUnitOfWork`, it uses a simpler architecture without `AsyncLocalStorage` or propagation modes—a deliberate trade-off that favors simplicity for scenarios where a single database connection is sufficient.
10
+
11
+ The test utilities export makes it easy to spin up in-memory databases and use generic repositories for test fixtures. In-memory SQLite databases are ephemeral: they're created instantly, run entirely in RAM, and disappear when the connection closes. This makes them ideal for integration tests that need database behavior without the overhead of a real PostgreSQL server.
12
+
13
+ ## When to Use SQLite vs PostgreSQL
14
+
15
+ | Scenario | Recommendation |
16
+ |----------|----------------|
17
+ | Unit/integration tests | **SQLite** - Fast, no external dependencies |
18
+ | Production database | **PostgreSQL** - Full ACID, scalability, advanced features |
19
+ | CI/CD pipelines | **SQLite** - No database setup required |
20
+ | Local development | Either - SQLite for speed, PostgreSQL for parity with production |
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install @hexaijs/sqlite
26
+ ```
27
+
28
+ **Peer dependencies:**
29
+
30
+ ```bash
31
+ npm install @hexaijs/core sqlite sqlite3
32
+ ```
33
+
34
+ ## Core Concepts
35
+
36
+ ### SqliteUnitOfWork
37
+
38
+ The `SqliteUnitOfWork` implements `UnitOfWork<Database>` from `@hexaijs/core`. It manages transaction lifecycle for a given SQLite database connection.
39
+
40
+ ```typescript
41
+ import { open } from "sqlite";
42
+ import sqlite3 from "sqlite3";
43
+ import { SqliteUnitOfWork } from "@hexaijs/sqlite";
44
+
45
+ // Create an in-memory database
46
+ const db = await open({
47
+ filename: ":memory:",
48
+ driver: sqlite3.Database,
49
+ });
50
+
51
+ // Create unit of work
52
+ const unitOfWork = new SqliteUnitOfWork(db);
53
+ ```
54
+
55
+ Unlike PostgreSQL's unit of work which accepts a client factory, `SqliteUnitOfWork` takes a pre-connected `Database` instance. This simpler model works well for SQLite's single-writer architecture.
56
+
57
+ ### Transaction Execution
58
+
59
+ Use `wrap()` to execute operations within a transaction:
60
+
61
+ ```typescript
62
+ const result = await unitOfWork.wrap(async (db) => {
63
+ await db.run("INSERT INTO orders (id, status) VALUES (?, ?)", [orderId, "pending"]);
64
+ await db.run("INSERT INTO order_items (order_id, product_id) VALUES (?, ?)", [orderId, productId]);
65
+ return { orderId };
66
+ });
67
+ // Transaction commits if successful
68
+ ```
69
+
70
+ If an error is thrown, the transaction rolls back:
71
+
72
+ ```typescript
73
+ try {
74
+ await unitOfWork.wrap(async (db) => {
75
+ await db.run("INSERT INTO orders (id, status) VALUES (?, ?)", [orderId, "pending"]);
76
+ throw new Error("Something went wrong");
77
+ });
78
+ } catch (error) {
79
+ // Transaction rolled back - no order was inserted
80
+ }
81
+ ```
82
+
83
+ ### Accessing the Client
84
+
85
+ Within a transaction, access the database through `getClient()`:
86
+
87
+ ```typescript
88
+ // Inside a command handler
89
+ const db = ctx.getUnitOfWork().getClient();
90
+ await db.run("UPDATE orders SET status = ? WHERE id = ?", ["confirmed", orderId]);
91
+ ```
92
+
93
+ Note: `getClient()` throws an error if called outside of a `wrap()` call.
94
+
95
+ ### Nested Transactions
96
+
97
+ Nested `wrap()` calls participate in the same transaction:
98
+
99
+ ```typescript
100
+ await unitOfWork.wrap(async (db) => {
101
+ await db.run("INSERT INTO orders (id) VALUES (?)", ["order-1"]);
102
+
103
+ await unitOfWork.wrap(async (db) => {
104
+ await db.run("INSERT INTO order_items (order_id) VALUES (?)", ["order-1"]);
105
+ });
106
+ // Both inserts are in the same transaction
107
+ });
108
+ // Single COMMIT at the end
109
+ ```
110
+
111
+ If any nested call throws, the entire transaction rolls back:
112
+
113
+ ```typescript
114
+ try {
115
+ await unitOfWork.wrap(async (db) => {
116
+ await db.run("INSERT INTO orders (id) VALUES (?)", ["order-1"]);
117
+
118
+ await unitOfWork.wrap(async (db) => {
119
+ await db.run("INSERT INTO order_items (order_id) VALUES (?)", ["order-1"]);
120
+ throw new Error("Nested failure");
121
+ });
122
+ });
123
+ } catch {
124
+ // Both inserts rolled back
125
+ }
126
+ ```
127
+
128
+ ## Usage
129
+
130
+ ### Test Setup
131
+
132
+ Use the test utilities for fast, isolated integration tests:
133
+
134
+ ```typescript
135
+ import type { Database } from "sqlite";
136
+ import { SqliteUnitOfWork } from "@hexaijs/sqlite";
137
+ import { getSqliteConnection } from "@hexaijs/sqlite/test";
138
+
139
+ describe("OrderRepository", () => {
140
+ let db: Database;
141
+ let unitOfWork: SqliteUnitOfWork;
142
+
143
+ beforeEach(async () => {
144
+ // Create fresh in-memory database
145
+ db = await getSqliteConnection();
146
+
147
+ // Create schema
148
+ await db.run(`
149
+ CREATE TABLE orders (
150
+ id TEXT PRIMARY KEY,
151
+ status TEXT NOT NULL
152
+ )
153
+ `);
154
+
155
+ unitOfWork = new SqliteUnitOfWork(db);
156
+ });
157
+
158
+ afterEach(async () => {
159
+ await db.close();
160
+ });
161
+
162
+ it("should persist orders", async () => {
163
+ await unitOfWork.wrap(async (db) => {
164
+ await db.run("INSERT INTO orders (id, status) VALUES (?, ?)", ["order-1", "pending"]);
165
+ });
166
+
167
+ const result = await db.get("SELECT * FROM orders WHERE id = ?", ["order-1"]);
168
+ expect(result.status).toBe("pending");
169
+ });
170
+ });
171
+ ```
172
+
173
+ ### SqliteRepositoryForTest
174
+
175
+ The `SqliteRepositoryForTest` provides a generic repository implementation for test fixtures. It implements the `Repository<E>` interface from `@hexaijs/core`.
176
+
177
+ ```typescript
178
+ import { SqliteRepositoryForTest, getSqliteConnection } from "@hexaijs/sqlite/test";
179
+ import { Identifiable, IdOf } from "@hexaijs/core";
180
+
181
+ // Define your entity
182
+ class Order implements Identifiable<OrderId> {
183
+ constructor(
184
+ private id: OrderId,
185
+ private status: string
186
+ ) {}
187
+
188
+ getId(): OrderId {
189
+ return this.id;
190
+ }
191
+
192
+ getStatus(): string {
193
+ return this.status;
194
+ }
195
+ }
196
+
197
+ // Define memento for serialization
198
+ interface OrderMemento {
199
+ id: string;
200
+ status: string;
201
+ }
202
+
203
+ // Create repository
204
+ const db = await getSqliteConnection();
205
+ const orderRepository = new SqliteRepositoryForTest<Order, OrderMemento>(db, {
206
+ namespace: "orders",
207
+ hydrate: (m) => new Order(new OrderId(m.id), m.status),
208
+ dehydrate: (e) => ({ id: e.getId().getValue(), status: e.getStatus() }),
209
+ });
210
+
211
+ // Use repository
212
+ await orderRepository.add(new Order(new OrderId("order-1"), "pending"));
213
+ const order = await orderRepository.get(new OrderId("order-1"));
214
+ await orderRepository.update(order);
215
+ const count = await orderRepository.count();
216
+ ```
217
+
218
+ The repository automatically creates its table on first use. Each repository uses a separate table identified by its namespace.
219
+
220
+ ### File-Based Database
221
+
222
+ For scenarios requiring persistence across test runs or debugging:
223
+
224
+ ```typescript
225
+ import { getSqliteConnection } from "@hexaijs/sqlite/test";
226
+
227
+ // File-based database instead of in-memory
228
+ const db = await getSqliteConnection("./test-database.sqlite");
229
+ ```
230
+
231
+ ## API Highlights
232
+
233
+ | Export | Description |
234
+ |--------|-------------|
235
+ | `SqliteUnitOfWork` | Transaction management implementing `UnitOfWork<Database>` |
236
+
237
+ **From `@hexaijs/sqlite/test`:**
238
+
239
+ | Export | Description |
240
+ |--------|-------------|
241
+ | `getSqliteConnection` | Creates SQLite connection (in-memory by default) |
242
+ | `SqliteRepositoryForTest` | Generic repository for test fixtures |
243
+
244
+ ## See Also
245
+
246
+ - [@hexaijs/core](../core/README.md) - Core interfaces (`UnitOfWork`, `Repository`)
247
+ - [@hexaijs/postgres](../postgres/README.md) - PostgreSQL implementation for production
248
+ - [@hexaijs/application](../application/README.md) - Application context that provides `getUnitOfWork()`
@@ -0,0 +1,2 @@
1
+ export * from "./sqlite-unit-of-work";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./sqlite-unit-of-work"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC"}
@@ -0,0 +1,10 @@
1
+ import type { Database } from "sqlite";
2
+ import { UnitOfWork } from "@hexaijs/core";
3
+ export declare class SqliteUnitOfWork implements UnitOfWork<Database> {
4
+ private db;
5
+ private static transactions;
6
+ constructor(db: Database);
7
+ getClient(): Database;
8
+ wrap<T>(fn: (client: Database) => Promise<T>): Promise<T>;
9
+ }
10
+ //# sourceMappingURL=sqlite-unit-of-work.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-unit-of-work.d.ts","sourceRoot":"","sources":["../src/sqlite-unit-of-work.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,qBAAa,gBAAiB,YAAW,UAAU,CAAC,QAAQ,CAAC;IAS7C,OAAO,CAAC,EAAE;IARtB,OAAO,CAAC,MAAM,CAAC,YAAY,CAMvB;gBAEgB,EAAE,EAAE,QAAQ;IAShC,SAAS,IAAI,QAAQ;IAQf,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAwBlE"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SqliteUnitOfWork = void 0;
4
+ class SqliteUnitOfWork {
5
+ db;
6
+ static transactions = new WeakMap();
7
+ constructor(db) {
8
+ this.db = db;
9
+ if (!SqliteUnitOfWork.transactions.has(db)) {
10
+ SqliteUnitOfWork.transactions.set(db, {
11
+ level: 0,
12
+ aborted: false,
13
+ });
14
+ }
15
+ }
16
+ getClient() {
17
+ const current = SqliteUnitOfWork.transactions.get(this.db);
18
+ if (!current || current.level === 0) {
19
+ throw new Error("No transaction is active");
20
+ }
21
+ return this.db;
22
+ }
23
+ async wrap(fn) {
24
+ const current = SqliteUnitOfWork.transactions.get(this.db);
25
+ if (++current.level === 1) {
26
+ await this.db.run("BEGIN TRANSACTION");
27
+ }
28
+ try {
29
+ return await fn(this.db);
30
+ }
31
+ catch (e) {
32
+ if (!current.aborted) {
33
+ current.aborted = true;
34
+ }
35
+ throw e;
36
+ }
37
+ finally {
38
+ if (--current.level === 0) {
39
+ if (current.aborted) {
40
+ await this.db.run("ROLLBACK");
41
+ }
42
+ else {
43
+ await this.db.run("COMMIT");
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ exports.SqliteUnitOfWork = SqliteUnitOfWork;
50
+ //# sourceMappingURL=sqlite-unit-of-work.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-unit-of-work.js","sourceRoot":"","sources":["../src/sqlite-unit-of-work.ts"],"names":[],"mappings":";;;AAIA,MAAa,gBAAgB;IASL;IARZ,MAAM,CAAC,YAAY,GAAG,IAAI,OAAO,EAMtC,CAAC;IAEJ,YAAoB,EAAY;QAAZ,OAAE,GAAF,EAAE,CAAU;QAC5B,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACzC,gBAAgB,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE;gBAClC,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,KAAK;aACjB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,SAAS;QACL,MAAM,OAAO,GAAG,gBAAgB,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC,EAAE,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,EAAoC;QAC9C,MAAM,OAAO,GAAG,gBAAgB,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAE,CAAC;QAC5D,IAAI,EAAE,OAAO,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,CAAC;YACD,OAAO,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;YAC3B,CAAC;YAED,MAAM,CAAC,CAAC;QACZ,CAAC;gBAAS,CAAC;YACP,IAAI,EAAE,OAAO,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gBACxB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;oBAClB,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAClC,CAAC;qBAAM,CAAC;oBACJ,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAChC,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;;AAjDL,4CAkDC"}
@@ -0,0 +1,3 @@
1
+ export * from "./sqlite-repository-for-test";
2
+ export * from "./utils";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,SAAS,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./sqlite-repository-for-test"), exports);
18
+ __exportStar(require("./utils"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+DAA6C;AAC7C,0CAAwB"}
@@ -0,0 +1,19 @@
1
+ import type { Database } from "sqlite";
2
+ import { Identifiable, IdOf, Repository } from "@hexaijs/core";
3
+ export declare class SqliteRepositoryForTest<E extends Identifiable<any>, M> implements Repository<E> {
4
+ protected db: Database;
5
+ protected namespace: string;
6
+ protected hydrate: (memento: M) => E;
7
+ protected dehydrate: (entity: E) => M;
8
+ constructor(db: Database, { namespace, hydrate, dehydrate, }: {
9
+ namespace: string;
10
+ hydrate: (memento: M) => E;
11
+ dehydrate: (entity: E) => M;
12
+ });
13
+ get(id: IdOf<E>): Promise<E>;
14
+ add(entity: E): Promise<void>;
15
+ update(entity: E): Promise<void>;
16
+ count(): Promise<number>;
17
+ protected ensureTableExists(): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=sqlite-repository-for-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-repository-for-test.d.ts","sourceRoot":"","sources":["../../src/test/sqlite-repository-for-test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAEH,YAAY,EACZ,IAAI,EAEJ,UAAU,EACb,MAAM,eAAe,CAAC;AAEvB,qBAAa,uBAAuB,CAChC,CAAC,SAAS,YAAY,CAAC,GAAG,CAAC,EAC3B,CAAC,CACH,YAAW,UAAU,CAAC,CAAC,CAAC;IAMlB,SAAS,CAAC,EAAE,EAAE,QAAQ;IAL1B,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;IACrC,SAAS,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;gBAGxB,EAAE,EAAE,QAAQ,EACtB,EACI,SAAS,EACT,OAAO,EACP,SAAS,GACZ,EAAE;QACC,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAC3B,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;KAC/B;IAOC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgB5B,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB7B,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBhC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;cAUd,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;CAQrD"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SqliteRepositoryForTest = void 0;
4
+ const core_1 = require("@hexaijs/core");
5
+ class SqliteRepositoryForTest {
6
+ db;
7
+ namespace;
8
+ hydrate;
9
+ dehydrate;
10
+ constructor(db, { namespace, hydrate, dehydrate, }) {
11
+ this.db = db;
12
+ this.namespace = namespace;
13
+ this.hydrate = hydrate;
14
+ this.dehydrate = dehydrate;
15
+ }
16
+ async get(id) {
17
+ await this.ensureTableExists();
18
+ const row = await this.db.get(`SELECT * FROM ${this.namespace} WHERE id = ?`, id.getValue());
19
+ if (!row) {
20
+ throw new core_1.ObjectNotFoundError(`entity with id '${id.getValue()}' not found`);
21
+ }
22
+ return this.hydrate(JSON.parse(row.data));
23
+ }
24
+ async add(entity) {
25
+ await this.ensureTableExists();
26
+ try {
27
+ await this.db.run(`INSERT INTO ${this.namespace} (id, data)
28
+ VALUES (?, ?)`, entity.getId().getValue(), JSON.stringify(this.dehydrate(entity)));
29
+ }
30
+ catch (e) {
31
+ if (e.message.includes("UNIQUE constraint failed")) {
32
+ throw new core_1.DuplicateObjectError(`entity with id '${entity
33
+ .getId()
34
+ .getValue()}' already exists`);
35
+ }
36
+ throw e;
37
+ }
38
+ }
39
+ async update(entity) {
40
+ await this.ensureTableExists();
41
+ const result = await this.db.run(`UPDATE ${this.namespace}
42
+ SET data = ?
43
+ WHERE id = ?`, JSON.stringify(this.dehydrate(entity)), entity.getId().getValue());
44
+ if (result.changes === 0) {
45
+ throw new core_1.ObjectNotFoundError(`entity with id '${entity.getId().getValue()}' not found`);
46
+ }
47
+ }
48
+ async count() {
49
+ await this.ensureTableExists();
50
+ const result = await this.db.get(`SELECT COUNT(*) AS count FROM ${this.namespace}`);
51
+ return result.count;
52
+ }
53
+ async ensureTableExists() {
54
+ await this.db.run(`
55
+ CREATE TABLE IF NOT EXISTS ${this.namespace} (
56
+ id TEXT NOT NULL PRIMARY KEY UNIQUE,
57
+ data TEXT NOT NULL
58
+ )
59
+ `);
60
+ }
61
+ }
62
+ exports.SqliteRepositoryForTest = SqliteRepositoryForTest;
63
+ //# sourceMappingURL=sqlite-repository-for-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-repository-for-test.js","sourceRoot":"","sources":["../../src/test/sqlite-repository-for-test.ts"],"names":[],"mappings":";;;AAEA,wCAMuB;AAEvB,MAAa,uBAAuB;IASlB;IALJ,SAAS,CAAS;IAClB,OAAO,CAAoB;IAC3B,SAAS,CAAmB;IAEtC,YACc,EAAY,EACtB,EACI,SAAS,EACT,OAAO,EACP,SAAS,GAKZ;QATS,OAAE,GAAF,EAAE,CAAU;QAWtB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAW;QACjB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CACzB,iBAAiB,IAAI,CAAC,SAAS,eAAe,EAC9C,EAAE,CAAC,QAAQ,EAAE,CAChB,CAAC;QACF,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,MAAM,IAAI,0BAAmB,CACzB,mBAAmB,EAAE,CAAC,QAAQ,EAAE,aAAa,CAChD,CAAC;QACN,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAS;QACf,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CACb,eAAe,IAAI,CAAC,SAAS;+BACd,EACf,MAAM,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EACzB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CACzC,CAAC;QACN,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,IAAK,CAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC;gBAC5D,MAAM,IAAI,2BAAoB,CAC1B,mBAAmB,MAAM;qBACpB,KAAK,EAAE;qBACP,QAAQ,EAAE,kBAAkB,CACpC,CAAC;YACN,CAAC;YAED,MAAM,CAAC,CAAC;QACZ,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAS;QAClB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAC5B,UAAU,IAAI,CAAC,SAAS;;8BAEN,EAClB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EACtC,MAAM,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,CAC5B,CAAC;QAEF,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,0BAAmB,CACzB,mBAAmB,MAAM,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,aAAa,CAC5D,CAAC;QACN,CAAC;IACL,CAAC;IAED,KAAK,CAAC,KAAK;QACP,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAC5B,iCAAiC,IAAI,CAAC,SAAS,EAAE,CACpD,CAAC;QAEF,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAES,KAAK,CAAC,iBAAiB;QAC7B,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;yCACe,IAAI,CAAC,SAAS;;;;SAI9C,CAAC,CAAC;IACP,CAAC;CACJ;AApGD,0DAoGC"}
@@ -0,0 +1,3 @@
1
+ import type { Database } from "sqlite";
2
+ export declare function getSqliteConnection(filename?: string): Promise<Database>;
3
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvC,wBAAsB,mBAAmB,CACrC,QAAQ,SAAa,GACtB,OAAO,CAAC,QAAQ,CAAC,CAOnB"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSqliteConnection = getSqliteConnection;
4
+ async function getSqliteConnection(filename = ":memory:") {
5
+ const sqlite = await import("sqlite");
6
+ const sqlite3 = await import("sqlite3");
7
+ return await sqlite.open({
8
+ filename,
9
+ driver: sqlite3.default.Database,
10
+ });
11
+ }
12
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":";;AAEA,kDASC;AATM,KAAK,UAAU,mBAAmB,CACrC,QAAQ,GAAG,UAAU;IAErB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IACxC,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC;QACrB,QAAQ;QACR,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ;KACnC,CAAC,CAAC;AACP,CAAC"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@hexaijs/sqlite",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.1.0",
7
+ "description": "SQLite support for hexai",
8
+ "license": "MIT",
9
+ "author": "Sangwoo Hyun <wkdny.hyun@gmail.com>",
10
+ "contributors": [
11
+ "Seungcheol Baek <victoryiron.baek@gmail.com>",
12
+ "Donghyun Lee <edonghyun@naver.com>"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/workingdanny911/hexai.git",
17
+ "directory": "packages/sqlite"
18
+ },
19
+ "homepage": "https://github.com/workingdanny911/hexai#readme",
20
+ "bugs": {
21
+ "url": "https://github.com/workingdanny911/hexai/issues"
22
+ },
23
+ "keywords": [
24
+ "hexai",
25
+ "hexagonal",
26
+ "clean-architecture",
27
+ "sqlite",
28
+ "database",
29
+ "typescript"
30
+ ],
31
+ "files": [
32
+ "dist",
33
+ "LICENSE"
34
+ ],
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "import": "./dist/index.js",
39
+ "require": "./dist/index.js"
40
+ },
41
+ "./test": {
42
+ "types": "./dist/test/index.d.ts",
43
+ "import": "./dist/test/index.js",
44
+ "require": "./dist/test/index.js"
45
+ },
46
+ "./package.json": "./package.json"
47
+ },
48
+ "dependencies": {},
49
+ "peerDependencies": {
50
+ "sqlite": "^5.1.1",
51
+ "sqlite3": "^5.1.7",
52
+ "@hexaijs/core": "^0.2.0"
53
+ },
54
+ "devDependencies": {
55
+ "sqlite": "^5.1.1",
56
+ "sqlite3": "^5.1.7"
57
+ },
58
+ "scripts": {
59
+ "test": "vitest run",
60
+ "build": "tsc -p ./tsconfig.build.json && tsc-alias"
61
+ }
62
+ }