Skip to content

Commit 3e3439b

Browse files
committed
docs: add README.md with usage examples and API documentation and update package.json description and enhance keywords
1 parent 12e5d85 commit 3e3439b

3 files changed

Lines changed: 267 additions & 3 deletions

File tree

README.md

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
# node-sqlite-map
2+
3+
A persistent `Map`-compatible API backed by SQLite using Node.js's built-in `node:sqlite` module. No external database dependencies — just a file (or `:memory:`).
4+
5+
## Requirements
6+
7+
- Node.js >= 22.5.0 (for `node:sqlite`)
8+
9+
## Installation
10+
11+
```bash
12+
npm install node-sqlite-map
13+
# or
14+
pnpm add node-sqlite-map
15+
```
16+
17+
## Quick Start
18+
19+
```typescript
20+
import { SqliteMap } from "node-sqlite-map"
21+
22+
const map = new SqliteMap("./data.db")
23+
24+
map.set("user:1", { name: "Kyle", role: "admin" })
25+
map.get("user:1") // { name: "Kyle", role: "admin" }
26+
map.has("user:1") // true
27+
map.size // 1
28+
```
29+
30+
Use `:memory:` for an in-memory database that does not persist:
31+
32+
```typescript
33+
const map = new SqliteMap(":memory:")
34+
```
35+
36+
## API
37+
38+
### Constructor
39+
40+
```typescript
41+
new SqliteMap<K extends string, V>(path: string, options?: DatabaseSyncOptions)
42+
```
43+
44+
| Parameter | Type | Description |
45+
| --------- | --------------------- | --------------------------------------------- |
46+
| `path` | `string` | Path to SQLite database file, or `":memory:"` |
47+
| `options` | `DatabaseSyncOptions` | Optional Node.js `DatabaseSync` options |
48+
49+
### Core Methods
50+
51+
#### `set(key, value): this`
52+
53+
Inserts or replaces a key-value pair. Returns `this` for chaining.
54+
55+
```typescript
56+
map.set("a", 1).set("b", 2).set("c", 3)
57+
```
58+
59+
#### `get(key): V | undefined`
60+
61+
Returns the value for the key, or `undefined` if not found.
62+
63+
```typescript
64+
map.get("a") // 1
65+
map.get("z") // undefined
66+
```
67+
68+
#### `has(key): boolean`
69+
70+
Returns `true` if the key exists.
71+
72+
```typescript
73+
map.has("a") // true
74+
```
75+
76+
#### `delete(key): boolean`
77+
78+
Removes the entry. Returns `true` if it existed, `false` otherwise.
79+
80+
```typescript
81+
map.delete("a") // true
82+
map.delete("a") // false
83+
```
84+
85+
#### `clear(): void`
86+
87+
Removes all entries.
88+
89+
```typescript
90+
map.clear()
91+
map.size // 0
92+
```
93+
94+
#### `getOrInsert(key, defaultValue): V`
95+
96+
Returns the existing value if the key exists, otherwise inserts `defaultValue` and returns it.
97+
98+
```typescript
99+
map.getOrInsert("count", 0) // inserts 0 and returns 0
100+
map.getOrInsert("count", 99) // returns 0 (already exists)
101+
```
102+
103+
#### `getOrInsertComputed(key, callbackFn): V`
104+
105+
Like `getOrInsert` but the default value is computed lazily via a callback — only called if the key is missing.
106+
107+
```typescript
108+
map.getOrInsertComputed("slug", (key) => key.toLowerCase().replace(" ", "-"))
109+
```
110+
111+
### Iteration
112+
113+
All iteration methods reflect the insertion order of keys.
114+
115+
#### `keys(): IterableIterator<K>`
116+
117+
```typescript
118+
for (const key of map.keys()) console.log(key) // "a", "b", "c"
119+
console.log([...map.keys()]) // ["a", "b", "c"]
120+
```
121+
122+
#### `values(): IterableIterator<V>`
123+
124+
```typescript
125+
console.log([...map.values()]) // [1, 2, 3]
126+
```
127+
128+
#### `entries(): IterableIterator<[K, V]>`
129+
130+
```typescript
131+
console.log([...map.entries()]) // [["a", 1], ["b", 2], ["c", 3]]
132+
```
133+
134+
#### `forEach(callback): void`
135+
136+
```typescript
137+
map.forEach((value, key, map) => {
138+
console.log(key, value)
139+
})
140+
```
141+
142+
#### `[Symbol.iterator]()`
143+
144+
Makes the map directly iterable — equivalent to `entries()`.
145+
146+
```typescript
147+
for (const [key, value] of map) {
148+
console.log(key, value)
149+
}
150+
```
151+
152+
### Properties
153+
154+
#### `size: number`
155+
156+
Returns the number of entries.
157+
158+
```typescript
159+
map.size // 3
160+
```
161+
162+
### Serialization
163+
164+
#### `toJSON(): Record<string, V>`
165+
166+
Returns a plain object representation. Called automatically by `JSON.stringify`.
167+
168+
```typescript
169+
map.set("x", 1)
170+
map.toJSON() // { x: 1 }
171+
JSON.stringify(map) // '{"x":1}'
172+
```
173+
174+
#### `[Symbol.toStringTag]: string`
175+
176+
Returns `"SqliteMap"`.
177+
178+
```typescript
179+
Object.prototype.toString.call(map) // "[object SqliteMap]"
180+
```
181+
182+
## Type Parameters
183+
184+
```typescript
185+
SqliteMap<K extends string, V>
186+
```
187+
188+
| Parameter | Constraint | Description |
189+
| --------- | ---------- | -------------------------------------- |
190+
| `K` | `string` | Key type — must be a string |
191+
| `V` | any | Value type — must be JSON-serializable |
192+
193+
> Values are stored as JSON strings internally, so any JSON-serializable value is supported: objects, arrays, numbers, booleans, strings, null.
194+
195+
## Examples
196+
197+
### Persistent cache
198+
199+
```typescript
200+
const cache = new SqliteMap<string, { data: unknown; expiresAt: number }>("./cache.db")
201+
202+
cache.getOrInsertComputed("api:users", () => ({
203+
data: fetchUsers(),
204+
expiresAt: Date.now() + 60_000
205+
}))
206+
```
207+
208+
### Counting
209+
210+
```typescript
211+
const hits = new SqliteMap<string, number>("./hits.db")
212+
213+
hits.getOrInsert("/home", 0)
214+
hits.set("/home", (hits.get("/home") ?? 0) + 1)
215+
```
216+
217+
### Spreading / converting
218+
219+
```typescript
220+
// To plain object
221+
const obj = sqliteMap.toJSON()
222+
223+
// To native Map
224+
const native = new Map(sqliteMap.entries())
225+
226+
// From array of entries
227+
for (const [k, v] of entries) sqliteMap.set(k, v)
228+
```
229+
230+
## Differences from native `Map`
231+
232+
| Feature | `Map` | `SqliteMap` |
233+
| ---------------- | ----------------- | ----------------- |
234+
| Persistence | ❌ In-memory only | ✅ File-backed |
235+
| Key type | Any | `string` only |
236+
| Value type | Any | JSON-serializable |
237+
| Iteration order | Insertion order | Insertion order |
238+
| `JSON.stringify` | `{}` (empty) | ✅ Full object |
239+
240+
## License
241+
242+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
243+
244+
## Links & Community
245+
246+
| Resource | URL |
247+
| ----------------- | ----------------------------------------------- |
248+
| GitHub repository | https://github.com/xcfio/node-sqlite-map |
249+
| npm package | https://www.npmjs.com/package/node-sqlite-map |
250+
| Homepage | https://github.com/xcfio/node-sqlite-map#readme |
251+
| Bug reports | https://github.com/xcfio/node-sqlite-map/issues |
252+
253+
### Discord
254+
255+
Join the community on Discord for help, and discussion:
256+
257+
**https://discord.gg/FaCCaFM74Q**
258+
259+
---
260+
261+
Made with ❤️ by [xcfio](https://github.com/xcfio)

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "node-sqlite-map",
33
"version": "0.0.1",
4-
"description": "",
4+
"description": "A persistent, Map-compatible key-value store for Node.js backed by node:sqlite",
55
"author": "xcfio",
66
"homepage": "https://github.com/xcfio/node-sqlite-map#readme",
77
"type": "commonjs",
@@ -15,9 +15,11 @@
1515
"build": "tsc"
1616
},
1717
"keywords": [
18+
"map",
19+
"cache",
1820
"sqlite",
19-
"node-sqlite",
20-
"map"
21+
"storage",
22+
"node-sqlite"
2123
],
2224
"repository": {
2325
"type": "git",

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { DatabaseSync, DatabaseSyncOptions } from "node:sqlite"
22
export { version } from "../package.json"
3+
export type { DatabaseSyncOptions }
34

45
export class SqliteMap<K extends string, V> {
56
private db: DatabaseSync

0 commit comments

Comments
 (0)