@pineliner/odb-client 1.1.3 → 1.1.4
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/database/types.d.ts +1 -0
- package/dist/database/types.d.ts.map +1 -1
- package/dist/index.cjs +40 -12
- package/dist/index.js +40 -12
- package/package.json +1 -1
- package/src/database/adapters/bun-sqlite.ts +21 -0
- package/src/database/adapters/libsql.ts +21 -0
- package/src/database/adapters/odblite.ts +25 -11
- package/src/database/types.ts +5 -0
package/dist/database/types.d.ts
CHANGED
|
@@ -58,6 +58,7 @@ export interface Connection {
|
|
|
58
58
|
prepare(sql: string): PreparedStatement;
|
|
59
59
|
transaction<T>(fn: (tx: Connection) => Promise<T>): Promise<T>;
|
|
60
60
|
begin<T>(fn: (tx: Connection) => Promise<T>): Promise<T>;
|
|
61
|
+
savepoint<T>(fn: (tx: Connection) => Promise<T>): Promise<T>;
|
|
61
62
|
close(): Promise<void>;
|
|
62
63
|
createORM?(): any;
|
|
63
64
|
databaseHash?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/database/types.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,cAAc,GACd,WAAW,GACX,WAAW,CAAA;AAEf;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAA;AAE7D;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG;IAClC,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IAEtB;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IAGzB,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;IAG3E,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAA;IAGvC,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5F,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IAClH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAA;IAGvC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC9D,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/database/types.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -1697,6 +1697,19 @@ var __webpack_exports__ = {};
|
|
|
1697
1697
|
async begin(fn) {
|
|
1698
1698
|
return this.transaction(fn);
|
|
1699
1699
|
}
|
|
1700
|
+
async savepoint(fn) {
|
|
1701
|
+
if (!this.inTransaction) return this.transaction(fn);
|
|
1702
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1703
|
+
try {
|
|
1704
|
+
await this.execute(`SAVEPOINT ${name}`);
|
|
1705
|
+
const result = await fn(this);
|
|
1706
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`);
|
|
1707
|
+
return result;
|
|
1708
|
+
} catch (error) {
|
|
1709
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(()=>{});
|
|
1710
|
+
throw error;
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1700
1713
|
async close() {
|
|
1701
1714
|
this.db.close();
|
|
1702
1715
|
}
|
|
@@ -1853,6 +1866,19 @@ var __webpack_exports__ = {};
|
|
|
1853
1866
|
async begin(fn) {
|
|
1854
1867
|
return this.transaction(fn);
|
|
1855
1868
|
}
|
|
1869
|
+
async savepoint(fn) {
|
|
1870
|
+
if (!this.txClient) return this.transaction(fn);
|
|
1871
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1872
|
+
try {
|
|
1873
|
+
await this.execute(`SAVEPOINT ${name}`);
|
|
1874
|
+
const result = await fn(this);
|
|
1875
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`);
|
|
1876
|
+
return result;
|
|
1877
|
+
} catch (error) {
|
|
1878
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(()=>{});
|
|
1879
|
+
throw error;
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1856
1882
|
async close() {}
|
|
1857
1883
|
createORM() {
|
|
1858
1884
|
const { createORM } = __webpack_require__("./src/orm/index.ts");
|
|
@@ -2020,18 +2046,7 @@ var __webpack_exports__ = {};
|
|
|
2020
2046
|
};
|
|
2021
2047
|
}
|
|
2022
2048
|
async transaction(fn) {
|
|
2023
|
-
if (this.inTransaction)
|
|
2024
|
-
const savepointName = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2025
|
-
try {
|
|
2026
|
-
await this.execute(`SAVEPOINT ${savepointName}`);
|
|
2027
|
-
const result = await fn(this);
|
|
2028
|
-
await this.execute(`RELEASE SAVEPOINT ${savepointName}`);
|
|
2029
|
-
return result;
|
|
2030
|
-
} catch (error) {
|
|
2031
|
-
await this.execute(`ROLLBACK TO SAVEPOINT ${savepointName}`).catch(()=>{});
|
|
2032
|
-
throw error;
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2049
|
+
if (this.inTransaction) return fn(this);
|
|
2035
2050
|
this.inTransaction = true;
|
|
2036
2051
|
try {
|
|
2037
2052
|
await this.execute('BEGIN');
|
|
@@ -2050,6 +2065,19 @@ var __webpack_exports__ = {};
|
|
|
2050
2065
|
async begin(fn) {
|
|
2051
2066
|
return this.transaction(fn);
|
|
2052
2067
|
}
|
|
2068
|
+
async savepoint(fn) {
|
|
2069
|
+
if (!this.inTransaction) return this.transaction(fn);
|
|
2070
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2071
|
+
try {
|
|
2072
|
+
await this.execute(`SAVEPOINT ${name}`);
|
|
2073
|
+
const result = await fn(this);
|
|
2074
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`);
|
|
2075
|
+
return result;
|
|
2076
|
+
} catch (error) {
|
|
2077
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(()=>{});
|
|
2078
|
+
throw error;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2053
2081
|
async close() {}
|
|
2054
2082
|
createORM() {
|
|
2055
2083
|
const { createORM } = __webpack_require__("./src/orm/index.ts");
|
package/dist/index.js
CHANGED
|
@@ -1606,6 +1606,19 @@ class BunSQLiteConnection {
|
|
|
1606
1606
|
async begin(fn) {
|
|
1607
1607
|
return this.transaction(fn);
|
|
1608
1608
|
}
|
|
1609
|
+
async savepoint(fn) {
|
|
1610
|
+
if (!this.inTransaction) return this.transaction(fn);
|
|
1611
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1612
|
+
try {
|
|
1613
|
+
await this.execute(`SAVEPOINT ${name}`);
|
|
1614
|
+
const result = await fn(this);
|
|
1615
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`);
|
|
1616
|
+
return result;
|
|
1617
|
+
} catch (error) {
|
|
1618
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(()=>{});
|
|
1619
|
+
throw error;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1609
1622
|
async close() {
|
|
1610
1623
|
this.db.close();
|
|
1611
1624
|
}
|
|
@@ -1761,6 +1774,19 @@ class LibSQLConnection {
|
|
|
1761
1774
|
async begin(fn) {
|
|
1762
1775
|
return this.transaction(fn);
|
|
1763
1776
|
}
|
|
1777
|
+
async savepoint(fn) {
|
|
1778
|
+
if (!this.txClient) return this.transaction(fn);
|
|
1779
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1780
|
+
try {
|
|
1781
|
+
await this.execute(`SAVEPOINT ${name}`);
|
|
1782
|
+
const result = await fn(this);
|
|
1783
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`);
|
|
1784
|
+
return result;
|
|
1785
|
+
} catch (error) {
|
|
1786
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(()=>{});
|
|
1787
|
+
throw error;
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1764
1790
|
async close() {}
|
|
1765
1791
|
createORM() {
|
|
1766
1792
|
const { createORM } = __webpack_require__("./src/orm/index.ts");
|
|
@@ -1928,18 +1954,7 @@ class ODBLiteConnection {
|
|
|
1928
1954
|
};
|
|
1929
1955
|
}
|
|
1930
1956
|
async transaction(fn) {
|
|
1931
|
-
if (this.inTransaction)
|
|
1932
|
-
const savepointName = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1933
|
-
try {
|
|
1934
|
-
await this.execute(`SAVEPOINT ${savepointName}`);
|
|
1935
|
-
const result = await fn(this);
|
|
1936
|
-
await this.execute(`RELEASE SAVEPOINT ${savepointName}`);
|
|
1937
|
-
return result;
|
|
1938
|
-
} catch (error) {
|
|
1939
|
-
await this.execute(`ROLLBACK TO SAVEPOINT ${savepointName}`).catch(()=>{});
|
|
1940
|
-
throw error;
|
|
1941
|
-
}
|
|
1942
|
-
}
|
|
1957
|
+
if (this.inTransaction) return fn(this);
|
|
1943
1958
|
this.inTransaction = true;
|
|
1944
1959
|
try {
|
|
1945
1960
|
await this.execute('BEGIN');
|
|
@@ -1958,6 +1973,19 @@ class ODBLiteConnection {
|
|
|
1958
1973
|
async begin(fn) {
|
|
1959
1974
|
return this.transaction(fn);
|
|
1960
1975
|
}
|
|
1976
|
+
async savepoint(fn) {
|
|
1977
|
+
if (!this.inTransaction) return this.transaction(fn);
|
|
1978
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1979
|
+
try {
|
|
1980
|
+
await this.execute(`SAVEPOINT ${name}`);
|
|
1981
|
+
const result = await fn(this);
|
|
1982
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`);
|
|
1983
|
+
return result;
|
|
1984
|
+
} catch (error) {
|
|
1985
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(()=>{});
|
|
1986
|
+
throw error;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1961
1989
|
async close() {}
|
|
1962
1990
|
createORM() {
|
|
1963
1991
|
const { createORM } = __webpack_require__("./src/orm/index.ts");
|
package/package.json
CHANGED
|
@@ -292,6 +292,27 @@ class BunSQLiteConnection implements Connection {
|
|
|
292
292
|
return this.transaction(fn)
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Execute function within an explicit savepoint for partial rollback isolation.
|
|
297
|
+
* If called outside a transaction, behaves like transaction().
|
|
298
|
+
*/
|
|
299
|
+
async savepoint<T>(fn: (tx: Connection) => Promise<T>): Promise<T> {
|
|
300
|
+
if (!this.inTransaction) {
|
|
301
|
+
return this.transaction(fn)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
305
|
+
try {
|
|
306
|
+
await this.execute(`SAVEPOINT ${name}`)
|
|
307
|
+
const result = await fn(this)
|
|
308
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`)
|
|
309
|
+
return result
|
|
310
|
+
} catch (error) {
|
|
311
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(() => {})
|
|
312
|
+
throw error
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
295
316
|
/**
|
|
296
317
|
* Close connection
|
|
297
318
|
*/
|
|
@@ -270,6 +270,27 @@ class LibSQLConnection implements Connection {
|
|
|
270
270
|
return this.transaction(fn)
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Execute function within an explicit savepoint for partial rollback isolation.
|
|
275
|
+
* If called outside a transaction, behaves like transaction().
|
|
276
|
+
*/
|
|
277
|
+
async savepoint<T>(fn: (tx: Connection) => Promise<T>): Promise<T> {
|
|
278
|
+
if (!this.txClient) {
|
|
279
|
+
return this.transaction(fn)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
283
|
+
try {
|
|
284
|
+
await this.execute(`SAVEPOINT ${name}`)
|
|
285
|
+
const result = await fn(this)
|
|
286
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`)
|
|
287
|
+
return result
|
|
288
|
+
} catch (error) {
|
|
289
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(() => {})
|
|
290
|
+
throw error
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
273
294
|
/**
|
|
274
295
|
* Close connection
|
|
275
296
|
*/
|
|
@@ -301,17 +301,10 @@ class ODBLiteConnection implements Connection {
|
|
|
301
301
|
*/
|
|
302
302
|
async transaction<T>(fn: (tx: Connection) => Promise<T>): Promise<T> {
|
|
303
303
|
if (this.inTransaction) {
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const result = await fn(this)
|
|
309
|
-
await this.execute(`RELEASE SAVEPOINT ${savepointName}`)
|
|
310
|
-
return result
|
|
311
|
-
} catch (error) {
|
|
312
|
-
await this.execute(`ROLLBACK TO SAVEPOINT ${savepointName}`).catch(() => {})
|
|
313
|
-
throw error
|
|
314
|
-
}
|
|
304
|
+
// Already in transaction - join existing transaction (no savepoint overhead).
|
|
305
|
+
// This allows convenience functions that each wrap in db.transaction()
|
|
306
|
+
// to be freely composed inside an outer transaction.
|
|
307
|
+
return fn(this)
|
|
315
308
|
}
|
|
316
309
|
|
|
317
310
|
this.inTransaction = true
|
|
@@ -345,6 +338,27 @@ class ODBLiteConnection implements Connection {
|
|
|
345
338
|
return this.transaction(fn)
|
|
346
339
|
}
|
|
347
340
|
|
|
341
|
+
/**
|
|
342
|
+
* Execute function within an explicit savepoint for partial rollback isolation.
|
|
343
|
+
* If called outside a transaction, behaves like transaction().
|
|
344
|
+
*/
|
|
345
|
+
async savepoint<T>(fn: (tx: Connection) => Promise<T>): Promise<T> {
|
|
346
|
+
if (!this.inTransaction) {
|
|
347
|
+
return this.transaction(fn)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const name = `sp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
351
|
+
try {
|
|
352
|
+
await this.execute(`SAVEPOINT ${name}`)
|
|
353
|
+
const result = await fn(this)
|
|
354
|
+
await this.execute(`RELEASE SAVEPOINT ${name}`)
|
|
355
|
+
return result
|
|
356
|
+
} catch (error) {
|
|
357
|
+
await this.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(() => {})
|
|
358
|
+
throw error
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
348
362
|
/**
|
|
349
363
|
* Close connection
|
|
350
364
|
*/
|
package/src/database/types.ts
CHANGED
|
@@ -77,6 +77,11 @@ export interface Connection {
|
|
|
77
77
|
transaction<T>(fn: (tx: Connection) => Promise<T>): Promise<T>
|
|
78
78
|
begin<T>(fn: (tx: Connection) => Promise<T>): Promise<T>
|
|
79
79
|
|
|
80
|
+
// Savepoint support — explicit partial rollback isolation within a transaction.
|
|
81
|
+
// Use when you need an inner operation to fail without rolling back the outer transaction.
|
|
82
|
+
// If called outside a transaction, behaves like transaction().
|
|
83
|
+
savepoint<T>(fn: (tx: Connection) => Promise<T>): Promise<T>
|
|
84
|
+
|
|
80
85
|
// Connection management
|
|
81
86
|
close(): Promise<void>
|
|
82
87
|
|