Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/beenotung/better-sqlite3-proxy
Efficiently proxy sqlite tables and access data as typical array of objects
https://github.com/beenotung/better-sqlite3-proxy
better-sqlite3 data-access-library data-access-object proxy sqlite sync typescript-library
Last synced: 30 days ago
JSON representation
Efficiently proxy sqlite tables and access data as typical array of objects
- Host: GitHub
- URL: https://github.com/beenotung/better-sqlite3-proxy
- Owner: beenotung
- License: bsd-2-clause
- Created: 2022-03-02T16:48:43.000Z (almost 3 years ago)
- Default Branch: master
- Last Pushed: 2024-04-09T20:16:23.000Z (10 months ago)
- Last Synced: 2024-05-10T02:42:40.388Z (9 months ago)
- Topics: better-sqlite3, data-access-library, data-access-object, proxy, sqlite, sync, typescript-library
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/better-sqlite3-proxy
- Size: 92.8 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# better-sqlite3-proxy
Efficiently proxy sqlite tables and access data as typical array of objects.
Powered by [better-sqlite3](https://github.com/WiseLibs/better-sqlite3)🔋[![npm Package Version](https://img.shields.io/npm/v/better-sqlite3-proxy)](https://www.npmjs.com/package/better-sqlite3-proxy)
## Features
- [x] Type safety support for each table
- [x] auto run sqlite statements, supports:
- [x] create table (only for key-value proxy)
- [x] select
- [x] insert
- [x] update
- [x] delete
- [x] auto resolve reference row from foreign key into nested objects like [ref-db](https://github.com/beenotung/ref-db)
- [x] auto convert column values into sqlite3 format
- [x] convert `true`/`false` to `1`/`0`
- [x] convert `Date` instance to GMT timestamp
- [x] support searching `null` / `not null` columns
- [x] extra helper functions:
- [x] toSqliteTimestamp (date): string
- [x] fromSqliteTimestamp (string_or_date): Date
- [x] seedRow (table, filter, extra?): number
- [x] upsert (table, key, date)
- [x] getId (table, key, value)### Array Operations Mapping
| Array Operation | Mapped SQL Operation |
| ------------------------ | ------------------------------------- |
| array.push(...object) | insert |
| array[id] = object | insert or update |
| update(array,id,partial) | update |
| find(array, filter) | select where filter limit 1 |
| filter(array, filter) | select where filter |
| count(array, filter) | select count where filter |
| delete array[id] | delete where id |
| del(array, filter) | delete where filter |
| array.length = length | delete where id > length |
| array.slice(start, end) | select where id >= start and id < end |for-of loop, array.forEach(fn), array.filter(fn) and array.map(fn) are also supported, they will receive proxy-ed rows.
Tips: You can use for-of loop instead of array.forEach(fn) if you may terminate the loop early
Tips: You can use filter(partial) instead of array.filter(fn) if possible for better performance
Tips: You can use update(array,id,partial) instead of Object.assign(row,partial) to update multiple columns in batch
Pro Tips: If you need complex query that can be expressed in sql, use prepared statement will have fastest runtime performance.
### Lazy Evaluation
The results from mapped operations are proxy-ed object identified by id.
Getting the properties on the object will trigger select on corresponding column, and
setting the properties will trigger update on corresponding column.## Usage Example
Remark: `@beenotung/better-sqlite3-helper` is a fork of `better-sqlite3-helper`. It updates the dependency on better-sqlite3 to v8+ which includes arm64 prebuilds for macOS.
Proxy Relational Tables (click to expand)
More Examples in [schema-proxy.spec.ts](./test/schema-proxy.spec.ts)
```typescript
import DB from '@beenotung/better-sqlite3-helper'
import { proxySchema, unProxy, find, filter } from 'better-sqlite3-proxy'let db = DB({
path: 'dev.sqlite3',
migrate: {
migrations: [
/* sql */ `
-- Up
create table if not exists user (
id integer primary key
, username text not null unique
);
-- Down
drop table user;
`,
/* sql */ `
-- Up
create table if not exists post (
id integer primary key
, user_id integer not null references user (id)
, content text not null
, created_at timestamp not null default current_timestamp
);
-- Down
drop table post;
`,
],
},
})type DBProxy = {
user: User[]
post: Post[]
}
type User = {
id?: number
username: string
}
type Post = {
id?: number
user_id: number
content: string
created_at?: string
author?: User
}let proxy = proxySchema(db, {
user: ['id', 'username'], // specify columns explicitly or leave it empty to auto-scan from create-table schema
post: [
['author', { field: 'user_id', table: 'user' }], // link up reference fields
],
})// insert record
proxy.user[1] = { username: 'alice' }
proxy.user.push({ username: 'Bob' })
proxy.post.push({ user_id: 1, content: 'Hello World' })// select a specific column
console.log(proxy.user[1].username) // 'alice'// select a specific column from reference table
console.log(proxy.post[1].author?.username) // 'alice'// select all columns of a record
console.log(unProxy(proxy.post[1])) // { id: 1, user_id: 1, content: 'Hello World', created_at: '2022-04-21 23:30:00'}// update a specific column
proxy.user[1].username = 'Alice'// update multiple columns
proxy.post[1] = {
content: 'Hello SQLite',
created_at: '2022-04-22 08:30:00',
} as Partial as Post// find by columns
console.log(find(proxy.user, { username: 'Alice' })?.id) // 1// filter by columns
console.log(filter(proxy.post, { user_id: 1 })[0].content) // 'Hello SQLite// delete record
delete proxy.user[2]
console.log(proxy.user.length) // 1// truncate table
proxy.post.length = 0
console.log(proxy.post.length) // 0
```Proxy Key-Value Records (click to expand)
More Examples in [key-value.spec.ts](./test/key-value-proxy.spec.ts)
```typescript
import DB from '@beenotung/better-sqlite3-helper'
import { proxyKeyValue, find, filter } from 'better-sqlite3-proxy'export let db = DB({
path: 'dev.sqlite3',
migrate: false,
})type DBProxy = {
users: {
id: number
username: string
}[]
}let proxy = proxyKeyValue(db)
// auto create users table, then insert record
proxy.users[1] = { id: 1, username: 'alice' }
proxy.users.push({ id: 2, username: 'Bob' })// select from users table
console.log(proxy.users[1]) // { id: 1, username: 'alice' }// update users table
proxy.users[1] = { id: 1, username: 'Alice' }
console.log(proxy.users[1]) // { id:1, username: 'Alice' }// find by columns
console.log(find(proxy.users, { username: 'Alice' })?.id) // 1// filter by columns
console.log(filter(proxy.users, { username: 'Bob' })[0].id) // 2// delete record
delete proxy.users[2]
console.log(proxy.users.length) // 1// truncate table
proxy.users.length = 0
console.log(proxy.users.length) // 0
```## License
This project is licensed with [BSD-2-Clause](./LICENSE)
This is free, libre, and open-source software. It comes down to four essential freedoms [[ref]](https://seirdy.one/2021/01/27/whatsapp-and-the-domestication-of-users.html#fnref:2):
- The freedom to run the program as you wish, for any purpose
- The freedom to study how the program works, and change it so it does your computing as you wish
- The freedom to redistribute copies so you can help others
- The freedom to distribute copies of your modified versions to others