bun-sqlite-key-value
Advanced tools
Comparing version 1.9.5 to 1.9.6
@@ -94,2 +94,7 @@ import { Database } from "bun:sqlite"; | ||
rename(oldKey: string, newKey: string): boolean; | ||
hSet<T = any>(key: string, field: string, value: T, ttlMs?: number): boolean; | ||
hGet<T = any>(key: string, field: string): T | undefined; | ||
hmSet<T = any>(key: string, fields: { | ||
[field: string]: T; | ||
}, ttlMs?: number): void; | ||
} |
@@ -328,8 +328,7 @@ // src/index.ts | ||
incr(key, incrBy = 1, ttlMs) { | ||
const self = this; | ||
return this.db.transaction(() => { | ||
const newValue = Number(self.get(key) ?? 0) + incrBy; | ||
const newValue = Number(this.get(key) ?? 0) + incrBy; | ||
if (isNaN(newValue)) | ||
return NaN; | ||
self.set(key, newValue, ttlMs); | ||
this.set(key, newValue, ttlMs); | ||
return newValue; | ||
@@ -342,6 +341,5 @@ }).immediate(); | ||
append(key, value, ttlMs) { | ||
const self = this; | ||
return this.db.transaction(() => { | ||
const newValue = String(self.get(key) ?? "") + value; | ||
self.set(key, newValue, ttlMs); | ||
const newValue = String(this.get(key) ?? "") + value; | ||
this.set(key, newValue, ttlMs); | ||
return newValue.length; | ||
@@ -351,6 +349,5 @@ }).immediate(); | ||
getSet(key, value, ttlMs) { | ||
const self = this; | ||
return this.db.transaction(() => { | ||
const oldValue = self.get(key); | ||
self.set(key, value, ttlMs); | ||
const oldValue = this.get(key); | ||
this.set(key, value, ttlMs); | ||
return oldValue; | ||
@@ -382,3 +379,3 @@ }).immediate(); | ||
if (this.has(oldKey)) { | ||
this.delete(newKey); | ||
this.deleteStatement.run({ key: newKey }); | ||
this.renameStatement.run({ oldKey, newKey }); | ||
@@ -389,4 +386,28 @@ return true; | ||
} | ||
})(); | ||
}).immediate(); | ||
} | ||
hSet(key, field, value, ttlMs) { | ||
return this.db.transaction(() => { | ||
const map = this.get(key) ?? new Map; | ||
const isNewField = !map.has(field); | ||
map.set(field, value); | ||
this.set(key, map, ttlMs); | ||
return isNewField; | ||
}).immediate(); | ||
} | ||
hGet(key, field) { | ||
const map = this.get(key); | ||
if (map === undefined) | ||
return; | ||
return map.get(field); | ||
} | ||
hmSet(key, fields, ttlMs) { | ||
this.db.transaction(() => { | ||
const map = this.get(key) ?? new Map; | ||
Object.entries(fields).forEach(([field, value]) => { | ||
map.set(field, value); | ||
}); | ||
this.set(key, map, ttlMs); | ||
}).immediate(); | ||
} | ||
} | ||
@@ -393,0 +414,0 @@ export { |
{ | ||
"name": "bun-sqlite-key-value", | ||
"version": "1.9.5", | ||
"version": "1.9.6", | ||
"author": { | ||
@@ -5,0 +5,0 @@ "name": "Gerold Penz", |
@@ -834,2 +834,92 @@ # Bun SQLite Key Value | ||
## Hash (Map Object) - Write Value | ||
```typescript | ||
hSet(key: string, field: string, value: any, ttlMs?: number) | ||
``` | ||
First the | ||
[JavaScript Map Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) | ||
is read from the database. | ||
If the data record does not yet exist, a new "Map Object" is created. | ||
Then the entry marked with `field` is added to the "Map Object" or overwritten. | ||
Finally, the modified "Map Object" is written back to the database. | ||
Inspired by: https://docs.keydb.dev/docs/commands/#hset | ||
### key | ||
The key must be a string. | ||
### field | ||
The field name must be a string. | ||
### value | ||
The value can be any object that can be serialized with | ||
[v8](https://github.com/nodejs/node/blob/main/doc/api/v8.md#serialization-api). | ||
This means that not only simple data types (string, number) are possible, | ||
but also more complex types such as sets or maps. | ||
You can find a list of the | ||
[supported data types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types) here. | ||
### ttlMs (optional) | ||
"Time to live" in milliseconds (for the database line, marked with `key`). | ||
After this time, the item becomes invalid and is deleted from the database | ||
the next time it is accessed or when the application is started. | ||
Set the value to 0 if you want to explicitly deactivate the process. | ||
### Example | ||
```typescript | ||
import { BunSqliteKeyValue } from "bun-sqlite-key-value" | ||
const store = new BunSqliteKeyValue() | ||
store.hSet("key-1", "field-name-1", "field-value-1") | ||
store.hSet("key-1", "field-name-2", "field-value-2") | ||
store.get("key-1") // --> Map(2) { | ||
"field-name-1": "field-value-1", | ||
"field-name-2": "field-value-2", | ||
} | ||
``` | ||
## Hash (Map Object) - Read Value | ||
```typescript | ||
hGet(key: string, field: string) | ||
``` | ||
First the | ||
[JavaScript Map Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) | ||
is read from the database. | ||
If the data record (marked with `key`) does not exist, `undefined` is returned. | ||
If the field (marked with `field`) does not exist in the "Map Object", `undefined` is returned. | ||
Inspired by: https://docs.keydb.dev/docs/commands/#hget | ||
### key | ||
The key must be a string. | ||
### field | ||
The field name must be a string. | ||
### Example | ||
```typescript | ||
import { BunSqliteKeyValue } from "bun-sqlite-key-value" | ||
const store = new BunSqliteKeyValue() | ||
store.hSet("key-1", "field-name-1", "field-value-1") | ||
store.hGet("key-1", "field-name-1") // --> "field-value-1" | ||
store.hGet("key-1", "field-name-2") // --> undefined | ||
``` | ||
## All Functions | ||
@@ -836,0 +926,0 @@ |
@@ -511,8 +511,7 @@ import { Database, type Statement } from "bun:sqlite" | ||
incr(key: string, incrBy: number = 1, ttlMs?: number): number { | ||
const self = this | ||
// @ts-ignore (Transaction returns a number or NaN, not void.) | ||
return this.db.transaction(() => { | ||
const newValue = Number(self.get<number>(key) ?? 0) + incrBy | ||
const newValue = Number(this.get<number>(key) ?? 0) + incrBy | ||
if (isNaN(newValue)) return NaN | ||
self.set<number>(key, newValue, ttlMs) | ||
this.set<number>(key, newValue, ttlMs) | ||
return newValue | ||
@@ -535,7 +534,6 @@ }).immediate() | ||
append(key: string, value: string, ttlMs?: number): number { | ||
const self = this | ||
// @ts-ignore (Transaction returns a number, not void.) | ||
return this.db.transaction(() => { | ||
const newValue = String(self.get<string>(key) ?? "") + value | ||
self.set<string>(key, newValue, ttlMs) | ||
const newValue = String(this.get<string>(key) ?? "") + value | ||
this.set<string>(key, newValue, ttlMs) | ||
return newValue.length | ||
@@ -549,7 +547,6 @@ }).immediate() | ||
getSet<T = any>(key: string, value: T, ttlMs?: number): T | undefined { | ||
const self = this | ||
// @ts-ignore (Transaction returns a number, not void.) | ||
return this.db.transaction(() => { | ||
const oldValue = self.get<T>(key) | ||
self.set<T>(key, value, ttlMs) | ||
const oldValue = this.get<T>(key) | ||
this.set<T>(key, value, ttlMs) | ||
return oldValue | ||
@@ -601,5 +598,6 @@ }).immediate() | ||
rename(oldKey: string, newKey: string): boolean { | ||
// @ts-ignore (Transaction returns boolean, not void.) | ||
return this.db.transaction(() => { | ||
if (this.has(oldKey)) { | ||
this.delete(newKey) | ||
this.deleteStatement.run({key: newKey}) | ||
this.renameStatement.run({oldKey, newKey}) | ||
@@ -610,3 +608,3 @@ return true | ||
} | ||
})() | ||
}).immediate() | ||
} | ||
@@ -624,23 +622,52 @@ | ||
// ToDo: hDel() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hdel | ||
// Do not use it with several large amounts of data or blobs. | ||
// This is because the entire data record with all fields is always read and written. | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hset | ||
hSet<T = any>(key: string, field: string, value: T, ttlMs?: number): boolean { | ||
// @ts-ignore (Transaction returns boolean, not void.) | ||
return this.db.transaction(() => { | ||
const map = this.get<Map<string, T>>(key) ?? new Map<string, T>() | ||
const isNewField: boolean = !map.has(field) | ||
map.set(field, value) | ||
this.set(key, map, ttlMs) | ||
return isNewField | ||
}).immediate() | ||
} | ||
// ToDo: hExists() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hexists | ||
// ToDo: hGet() | ||
// Do not use it with several large amounts of data or blobs. | ||
// This is because the entire data record with all fields is always read and written. | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hget | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hmget | ||
hGet<T = any>(key: string, field: string): T | undefined { | ||
const map = this.get<Map<string, T>>(key) | ||
if (map === undefined) return undefined | ||
return map.get(field) | ||
} | ||
// ToDo: hIncrBy() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hincrby | ||
// Do not use it with several large amounts of data or blobs. | ||
// This is because the entire data record with all fields is always read and written. | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hmset | ||
hmSet<T = any>(key: string, fields: {[field: string]: T}, ttlMs?: number) { | ||
this.db.transaction(() => { | ||
const map = this.get<Map<string, T>>(key) ?? new Map<string, T>() | ||
Object.entries(fields).forEach(([field, value]) => { | ||
map.set(field, value) | ||
}) | ||
this.set(key, map, ttlMs) | ||
}).immediate() | ||
} | ||
// ToDo: hKeys() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hkeys | ||
// ToDo: hmGet() | ||
// Do not use it with several large amounts of data or blobs. | ||
// This is because the entire data record with all fields is always read and written. | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hmget | ||
// ToDo: hExists() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hexists | ||
// ToDo: hLen() | ||
@@ -650,5 +677,4 @@ // Inspired by: https://docs.keydb.dev/docs/commands/#hlen | ||
// ToDo: hSet() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hset | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hmset | ||
// ToDo: hKeys() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hkeys | ||
@@ -661,5 +687,15 @@ | ||
// ToDo: hVals() | ||
// Do not use it with several large amounts of data or blobs. | ||
// This is because the entire data record with all fields is always read and written. | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hvals | ||
// ToDo: hDel() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hdel | ||
// ToDo: hIncrBy() | ||
// Inspired by: https://docs.keydb.dev/docs/commands/#hincrby | ||
// ToDo: lIndex() | ||
@@ -666,0 +702,0 @@ // Inspired by: https://docs.keydb.dev/docs/commands/#lindex |
69702
1105
1031