@hexaijs/sqlite 0.3.0 → 0.4.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/README.md +33 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +46 -4
- package/dist/index.js.map +1 -1
- package/package.json +60 -60
package/README.md
CHANGED
|
@@ -104,6 +104,39 @@ await db.run("UPDATE orders SET status = ? WHERE id = ?", ["confirmed", orderId]
|
|
|
104
104
|
|
|
105
105
|
Note: `getClient()` throws an error if called outside of a `scope()` or `wrap()` call.
|
|
106
106
|
|
|
107
|
+
### Transaction Lifecycle Hooks
|
|
108
|
+
|
|
109
|
+
Register callbacks that execute at specific points in the transaction lifecycle:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
await unitOfWork.scope(async () => {
|
|
113
|
+
unitOfWork.beforeCommit(async () => {
|
|
114
|
+
// Validate before committing
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
unitOfWork.afterCommit(async () => {
|
|
118
|
+
// Notify after successful commit
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
unitOfWork.afterRollback(async () => {
|
|
122
|
+
// Clean up on failure
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const db = unitOfWork.getClient();
|
|
126
|
+
await db.run("INSERT INTO orders (id, status) VALUES (?, ?)", [orderId, "pending"]);
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Hooks follow the same semantics as `@hexaijs/postgres`:
|
|
131
|
+
|
|
132
|
+
| Hook | When | On failure |
|
|
133
|
+
|------|------|------------|
|
|
134
|
+
| `beforeCommit` | Before COMMIT | Transaction rolls back instead |
|
|
135
|
+
| `afterCommit` | After COMMIT | Best-effort (errors → `AggregateError`) |
|
|
136
|
+
| `afterRollback` | After ROLLBACK | Best-effort (errors → `AggregateError`) |
|
|
137
|
+
|
|
138
|
+
Hooks are scope-local and can only be registered inside an active `scope()`.
|
|
139
|
+
|
|
107
140
|
### Nested Transactions
|
|
108
141
|
|
|
109
142
|
Nested `scope()` calls participate in the same transaction:
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { Database } from 'sqlite';
|
|
2
|
-
import { UnitOfWork } from '@hexaijs/core';
|
|
2
|
+
import { UnitOfWork, TransactionHook } from '@hexaijs/core';
|
|
3
3
|
|
|
4
4
|
declare class SqliteUnitOfWork implements UnitOfWork<Database> {
|
|
5
5
|
private db;
|
|
6
6
|
private static transactions;
|
|
7
7
|
constructor(db: Database);
|
|
8
8
|
getClient(): Database;
|
|
9
|
+
beforeCommit(hook: TransactionHook): void;
|
|
10
|
+
afterCommit(hook: TransactionHook): void;
|
|
11
|
+
afterRollback(hook: TransactionHook): void;
|
|
9
12
|
scope<T>(fn: () => Promise<T>): Promise<T>;
|
|
10
13
|
wrap<T>(fn: (client: Database) => Promise<T>): Promise<T>;
|
|
14
|
+
private getRequiredState;
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
export { SqliteUnitOfWork };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { TransactionHooks } from '@hexaijs/core';
|
|
2
|
+
|
|
1
3
|
// src/sqlite-unit-of-work.ts
|
|
2
4
|
var SqliteUnitOfWork = class _SqliteUnitOfWork {
|
|
3
5
|
constructor(db) {
|
|
@@ -5,7 +7,8 @@ var SqliteUnitOfWork = class _SqliteUnitOfWork {
|
|
|
5
7
|
if (!_SqliteUnitOfWork.transactions.has(db)) {
|
|
6
8
|
_SqliteUnitOfWork.transactions.set(db, {
|
|
7
9
|
level: 0,
|
|
8
|
-
aborted: false
|
|
10
|
+
aborted: false,
|
|
11
|
+
hooks: new TransactionHooks()
|
|
9
12
|
});
|
|
10
13
|
}
|
|
11
14
|
}
|
|
@@ -17,6 +20,18 @@ var SqliteUnitOfWork = class _SqliteUnitOfWork {
|
|
|
17
20
|
}
|
|
18
21
|
return this.db;
|
|
19
22
|
}
|
|
23
|
+
beforeCommit(hook) {
|
|
24
|
+
const current = this.getRequiredState("beforeCommit");
|
|
25
|
+
current.hooks.addBeforeCommit(hook);
|
|
26
|
+
}
|
|
27
|
+
afterCommit(hook) {
|
|
28
|
+
const current = this.getRequiredState("afterCommit");
|
|
29
|
+
current.hooks.addAfterCommit(hook);
|
|
30
|
+
}
|
|
31
|
+
afterRollback(hook) {
|
|
32
|
+
const current = this.getRequiredState("afterRollback");
|
|
33
|
+
current.hooks.addAfterRollback(hook);
|
|
34
|
+
}
|
|
20
35
|
async scope(fn) {
|
|
21
36
|
return this.wrap(fn);
|
|
22
37
|
}
|
|
@@ -25,23 +40,50 @@ var SqliteUnitOfWork = class _SqliteUnitOfWork {
|
|
|
25
40
|
if (++current.level === 1) {
|
|
26
41
|
await this.db.run("BEGIN TRANSACTION");
|
|
27
42
|
}
|
|
43
|
+
let abortError;
|
|
28
44
|
try {
|
|
29
45
|
return await fn(this.db);
|
|
30
46
|
} catch (e) {
|
|
31
47
|
if (!current.aborted) {
|
|
32
48
|
current.aborted = true;
|
|
33
49
|
}
|
|
50
|
+
abortError = e;
|
|
34
51
|
throw e;
|
|
35
52
|
} finally {
|
|
36
53
|
if (--current.level === 0) {
|
|
37
|
-
|
|
38
|
-
|
|
54
|
+
const hooks = current.hooks;
|
|
55
|
+
const wasAborted = current.aborted;
|
|
56
|
+
current.hooks = new TransactionHooks();
|
|
57
|
+
current.aborted = false;
|
|
58
|
+
if (wasAborted) {
|
|
59
|
+
await hooks.executeRollback(
|
|
60
|
+
async () => {
|
|
61
|
+
await this.db.run("ROLLBACK");
|
|
62
|
+
},
|
|
63
|
+
abortError
|
|
64
|
+
);
|
|
39
65
|
} else {
|
|
40
|
-
await
|
|
66
|
+
await hooks.executeCommit(
|
|
67
|
+
async () => {
|
|
68
|
+
await this.db.run("COMMIT");
|
|
69
|
+
},
|
|
70
|
+
async () => {
|
|
71
|
+
await this.db.run("ROLLBACK");
|
|
72
|
+
}
|
|
73
|
+
);
|
|
41
74
|
}
|
|
42
75
|
}
|
|
43
76
|
}
|
|
44
77
|
}
|
|
78
|
+
getRequiredState(hookName) {
|
|
79
|
+
const current = _SqliteUnitOfWork.transactions.get(this.db);
|
|
80
|
+
if (!current || current.level === 0) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Cannot register ${hookName} hook outside of a transaction scope`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
return current;
|
|
86
|
+
}
|
|
45
87
|
};
|
|
46
88
|
|
|
47
89
|
export { SqliteUnitOfWork };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sqlite-unit-of-work.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/sqlite-unit-of-work.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Database } from \"sqlite\";\n\nimport { TransactionHooks, UnitOfWork } from \"@hexaijs/core\";\nimport type { TransactionHook } from \"@hexaijs/core\";\n\nexport class SqliteUnitOfWork implements UnitOfWork<Database> {\n private static transactions = new WeakMap<\n Database,\n {\n level: number;\n aborted: boolean;\n hooks: TransactionHooks;\n }\n >();\n\n constructor(private db: Database) {\n if (!SqliteUnitOfWork.transactions.has(db)) {\n SqliteUnitOfWork.transactions.set(db, {\n level: 0,\n aborted: false,\n hooks: new TransactionHooks(),\n });\n }\n }\n\n getClient(): Database {\n const current = SqliteUnitOfWork.transactions.get(this.db);\n if (!current || current.level === 0) {\n throw new Error(\"No transaction is active\");\n }\n return this.db;\n }\n\n beforeCommit(hook: TransactionHook): void {\n const current = this.getRequiredState(\"beforeCommit\");\n current.hooks.addBeforeCommit(hook);\n }\n\n afterCommit(hook: TransactionHook): void {\n const current = this.getRequiredState(\"afterCommit\");\n current.hooks.addAfterCommit(hook);\n }\n\n afterRollback(hook: TransactionHook): void {\n const current = this.getRequiredState(\"afterRollback\");\n current.hooks.addAfterRollback(hook);\n }\n\n async scope<T>(fn: () => Promise<T>): Promise<T> {\n return this.wrap(fn);\n }\n\n async wrap<T>(fn: (client: Database) => Promise<T>): Promise<T> {\n const current = SqliteUnitOfWork.transactions.get(this.db)!;\n if (++current.level === 1) {\n await this.db.run(\"BEGIN TRANSACTION\");\n }\n\n let abortError: unknown;\n try {\n return await fn(this.db);\n } catch (e) {\n if (!current.aborted) {\n current.aborted = true;\n }\n abortError = e;\n\n throw e;\n } finally {\n if (--current.level === 0) {\n const hooks = current.hooks;\n const wasAborted = current.aborted;\n\n current.hooks = new TransactionHooks();\n current.aborted = false;\n\n if (wasAborted) {\n await hooks.executeRollback(\n async () => { await this.db.run(\"ROLLBACK\"); },\n abortError\n );\n } else {\n await hooks.executeCommit(\n async () => { await this.db.run(\"COMMIT\"); },\n async () => { await this.db.run(\"ROLLBACK\"); }\n );\n }\n }\n }\n }\n\n private getRequiredState(hookName: string) {\n const current = SqliteUnitOfWork.transactions.get(this.db);\n if (!current || current.level === 0) {\n throw new Error(\n `Cannot register ${hookName} hook outside of a transaction scope`\n );\n }\n return current;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
"name": "@hexaijs/sqlite",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"version": "0.4.0",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"description": "SQLite support for hexai",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Sangwoo Hyun <wkdny.hyun@gmail.com>",
|
|
11
|
+
"contributors": [
|
|
12
|
+
"Seungcheol Baek <victoryiron.baek@gmail.com>",
|
|
13
|
+
"Donghyun Lee <edonghyun@naver.com>"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/workingdanny911/hexai.git",
|
|
18
|
+
"directory": "packages/sqlite"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/workingdanny911/hexai#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/workingdanny911/hexai/issues"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"hexai",
|
|
26
|
+
"hexagonal",
|
|
27
|
+
"clean-architecture",
|
|
28
|
+
"sqlite",
|
|
29
|
+
"database",
|
|
30
|
+
"typescript"
|
|
31
|
+
],
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"exports": {
|
|
37
|
+
".": {
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"import": "./dist/index.js"
|
|
5
40
|
},
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"license": "MIT",
|
|
10
|
-
"author": "Sangwoo Hyun <wkdny.hyun@gmail.com>",
|
|
11
|
-
"contributors": [
|
|
12
|
-
"Seungcheol Baek <victoryiron.baek@gmail.com>",
|
|
13
|
-
"Donghyun Lee <edonghyun@naver.com>"
|
|
14
|
-
],
|
|
15
|
-
"repository": {
|
|
16
|
-
"type": "git",
|
|
17
|
-
"url": "git+https://github.com/workingdanny911/hexai.git",
|
|
18
|
-
"directory": "packages/sqlite"
|
|
41
|
+
"./test": {
|
|
42
|
+
"types": "./dist/test/index.d.ts",
|
|
43
|
+
"import": "./dist/test/index.js"
|
|
19
44
|
},
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"import": "./dist/index.js"
|
|
40
|
-
},
|
|
41
|
-
"./test": {
|
|
42
|
-
"types": "./dist/test/index.d.ts",
|
|
43
|
-
"import": "./dist/test/index.js"
|
|
44
|
-
},
|
|
45
|
-
"./package.json": "./package.json"
|
|
46
|
-
},
|
|
47
|
-
"scripts": {
|
|
48
|
-
"test": "vitest run",
|
|
49
|
-
"build": "tsup"
|
|
50
|
-
},
|
|
51
|
-
"dependencies": {},
|
|
52
|
-
"peerDependencies": {
|
|
53
|
-
"@hexaijs/core": "^0.7.0",
|
|
54
|
-
"sqlite": "^5.1.1",
|
|
55
|
-
"sqlite3": "^5.1.7"
|
|
56
|
-
},
|
|
57
|
-
"devDependencies": {
|
|
58
|
-
"@hexaijs/core": "workspace:^",
|
|
59
|
-
"@hexaijs/tooling": "workspace:*",
|
|
60
|
-
"sqlite": "^5.1.1",
|
|
61
|
-
"sqlite3": "^5.1.7"
|
|
62
|
-
}
|
|
63
|
-
}
|
|
45
|
+
"./package.json": "./package.json"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@hexaijs/core": "^0.8.0",
|
|
50
|
+
"sqlite": "^5.1.1",
|
|
51
|
+
"sqlite3": "^5.1.7"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"sqlite": "^5.1.1",
|
|
55
|
+
"sqlite3": "^5.1.7",
|
|
56
|
+
"@hexaijs/core": "^0.8.0",
|
|
57
|
+
"@hexaijs/tooling": "0.1.0"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"test": "vitest run",
|
|
61
|
+
"build": "tsup"
|
|
62
|
+
}
|
|
63
|
+
}
|