muya 2.2.8 → 2.2.9
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/esm/sqlite/table/table.js +2 -2
- package/package.json +1 -1
- package/src/__tests__/bench.test.tsx +7 -0
- package/src/__tests__/test-utils.ts +5 -0
- package/src/create-state.ts +7 -0
- package/src/create.ts +17 -1
- package/src/debug/development-tools.ts +15 -0
- package/src/scheduler.ts +6 -0
- package/src/select.ts +22 -2
- package/src/sqlite/__tests__/use-sqlite.test.tsx +1 -0
- package/src/sqlite/create-sqlite.ts +52 -0
- package/src/sqlite/select-sql.ts +10 -0
- package/src/sqlite/table/bun-backend.ts +9 -0
- package/src/sqlite/table/table.ts +27 -2
- package/src/sqlite/table/where.ts +29 -12
- package/src/sqlite/use-sqlite.ts +8 -0
- package/src/use-value.ts +7 -0
- package/src/utils/common.ts +10 -0
- package/src/utils/create-emitter.ts +3 -2
- package/src/utils/is.ts +3 -0
- package/src/utils/shallow.ts +7 -0
- package/types/__tests__/test-utils.d.ts +5 -0
- package/types/create-state.d.ts +2 -0
- package/types/create.d.ts +4 -1
- package/types/debug/development-tools.d.ts +5 -0
- package/types/select.d.ts +5 -2
- package/types/sqlite/create-sqlite.d.ts +5 -0
- package/types/sqlite/select-sql.d.ts +6 -0
- package/types/sqlite/table/bun-backend.d.ts +4 -0
- package/types/sqlite/table/table.d.ts +17 -0
- package/types/sqlite/table/where.d.ts +11 -0
- package/types/sqlite/use-sqlite.d.ts +8 -0
- package/types/use-value.d.ts +7 -0
- package/types/utils/common.d.ts +10 -0
- package/types/utils/create-emitter.d.ts +3 -2
- package/types/utils/shallow.d.ts +7 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{getWhereQuery as
|
|
1
|
+
import{getWhereQuery as p}from"./where";const O=500,N=100;function D(E){return"$."+E}function I(E,n){if(!(!E||!n))return n.split(".").reduce((r,y)=>{if(typeof r=="object"&&r!==null&&y in r)return r[y]},E)}async function M(E){const{backend:n,tableName:r,indexes:y,key:S,disablePragmaOptimization:$}=E,d=S!==void 0;$||(await n.execute("PRAGMA journal_mode=WAL;"),await n.execute("PRAGMA synchronous=NORMAL;"),await n.execute("PRAGMA temp_store=MEMORY;"),await n.execute("PRAGMA cache_size=-20000;")),d?await n.execute(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS ${r} (
|
|
3
3
|
key TEXT PRIMARY KEY,
|
|
4
4
|
data TEXT NOT NULL
|
|
@@ -8,4 +8,4 @@ import{getWhereQuery as h}from"./where";const O=500,N=100;function D(E){return"$
|
|
|
8
8
|
data TEXT NOT NULL
|
|
9
9
|
);
|
|
10
10
|
`);for(const t of y??[]){const o=String(t);await n.execute(`CREATE INDEX IF NOT EXISTS idx_${r}_${o.replaceAll(/\W/g,"_")}
|
|
11
|
-
ON ${r} (json_extract(data, '${D(o)}'));`)}function k(t){if(d)return I(t,String(S))}async function g(t){return(await t.select("SELECT changes() AS c"))[0]?.c??0}const
|
|
11
|
+
ON ${r} (json_extract(data, '${D(o)}'));`)}function k(t){if(d)return I(t,String(S))}async function g(t){return(await t.select("SELECT changes() AS c"))[0]?.c??0}const h={backend:n,async set(t,o){const e=o??n,a=JSON.stringify(t);if(d){const s=k(t);if(s==null)throw new Error(`Document is missing the configured key "${String(S)}". Provide it or create the table without "key".`);if(await e.execute(`UPDATE ${r} SET data = ? WHERE key = ?`,[a,s]),await g(e)===1)return{key:s,op:"update"};try{return await e.execute(`INSERT INTO ${r} (key, data) VALUES (?, ?)`,[s,a]),{key:s,op:"insert"}}catch{return await e.execute(`UPDATE ${r} SET data = ? WHERE key = ?`,[a,s]),{key:s,op:"update"}}}await e.execute(`INSERT INTO ${r} (data) VALUES (?)`,[a]);const u=(await e.select("SELECT last_insert_rowid() AS id"))[0]?.id;if(typeof u!="number")throw new Error("Failed to retrieve last_insert_rowid()");return{key:u,op:"insert"}},async get(t,o=e=>e){const e=d?"key = ?":"rowid = ?",a=await n.select(`SELECT rowid, data FROM ${r} WHERE ${e}`,[t]);if(a.length===0)return;const{data:i,rowid:u}=a[0],s=JSON.parse(i);return o(s,{rowId:u})},async delete(t){const o=d?"key = ?":"rowid = ?";if(await n.execute(`DELETE FROM ${r} WHERE ${o}`,[t]),((await n.select("SELECT changes() AS c"))[0]?.c??0)>0)return{key:t,op:"delete"}},async*search(t={}){const{sortBy:o,order:e="asc",limit:a,offset:i=0,where:u,select:s=l=>l,stepSize:c=N}=t,w=p(u),f=`SELECT rowid, data FROM ${r} ${w}`;let T=0,A=i;for(;;){let l=f;o?l+=` ORDER BY json_extract(data, '${D(String(o))}') COLLATE NOCASE ${e.toUpperCase()}`:l+=d?` ORDER BY key COLLATE NOCASE ${e.toUpperCase()}`:` ORDER BY rowid ${e.toUpperCase()}`;const R=a?Math.min(c,a-T):c;l+=` LIMIT ${R} OFFSET ${A}`;const m=await n.select(l);if(m.length===0)break;for(const{rowid:b,data:L}of m){if(a&&T>=a)return;const x=JSON.parse(L);yield s(x,{rowId:b}),T++}if(m.length<R||a&&T>=a)break;A+=m.length}},async count(t={}){const o=p(t.where),e=`SELECT COUNT(*) as count FROM ${r} ${o}`;return(await n.select(e))[0]?.count??0},async deleteBy(t){const o=p(t),e=d?"key":"rowid",a=[];return await n.transaction(async i=>{const u=await i.select(`SELECT ${e} AS k FROM ${r} ${o}`);if(u.length===0)return;const s=u.map(c=>c.k);for(let c=0;c<s.length;c+=O){const w=s.slice(c,c+O),f=w.map(()=>"?").join(",");await i.execute(`DELETE FROM ${r} WHERE ${e} IN (${f})`,w)}for(const c of s)a.push({key:c,op:"delete"})}),a},async clear(){await n.execute(`DELETE FROM ${r}`)},async batchSet(t){const o=[];return await n.transaction(async e=>{for(const a of t){const i=await h.set(a,e);o.push(i)}}),o}};return h}export{N as DEFAULT_STEP_SIZE,M as createTable,I as getByPath,D as toJsonPath};
|
package/package.json
CHANGED
|
@@ -12,6 +12,13 @@ import { useValue } from '../use-value'
|
|
|
12
12
|
import { atom, useAtom } from 'jotai'
|
|
13
13
|
import { create } from '../create'
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Utility to render a hook and measure the time it takes to reach a certain state
|
|
17
|
+
* @param hook The hook to render
|
|
18
|
+
* @param getValue Function to extract the value to monitor from the hook's return data
|
|
19
|
+
* @param toBe The target value to wait for
|
|
20
|
+
* @returns An object containing the hook's result, a waitFor function, and a promise that resolves with the time taken
|
|
21
|
+
*/
|
|
15
22
|
function renderPerfHook<T>(hook: () => T, getValue: (data: T) => number, toBe: number) {
|
|
16
23
|
let onResolve = (_value: number) => {}
|
|
17
24
|
const resolvePromise = new Promise<number>((resolve) => {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/* eslint-disable unicorn/prevent-abbreviations */
|
|
2
2
|
import { Component } from 'react'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Create a promise that resolves after a specified time
|
|
6
|
+
* @param time Time in ms to wait
|
|
7
|
+
* @returns A promise that resolves after the specified time
|
|
8
|
+
*/
|
|
4
9
|
export function longPromise(time = 200): Promise<number> {
|
|
5
10
|
return new Promise((resolve) => {
|
|
6
11
|
setTimeout(() => {
|
package/src/create-state.ts
CHANGED
|
@@ -12,6 +12,11 @@ interface GetStateOptions<T> {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
let stateId = 0
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate a unique state ID
|
|
18
|
+
* @returns A unique state ID
|
|
19
|
+
*/
|
|
15
20
|
function getStateId() {
|
|
16
21
|
return stateId++
|
|
17
22
|
}
|
|
@@ -19,6 +24,8 @@ function getStateId() {
|
|
|
19
24
|
type FullState<T> = GetStateOptions<T>['set'] extends undefined ? GetState<T> : State<T>
|
|
20
25
|
/**
|
|
21
26
|
* This is just utility function to create state base data
|
|
27
|
+
* @param options Options to create state
|
|
28
|
+
* @returns FullState<T>
|
|
22
29
|
*/
|
|
23
30
|
export function createState<T>(options: GetStateOptions<T>): FullState<T> {
|
|
24
31
|
const { get, destroy, set, getSnapshot } = options
|
package/src/create.ts
CHANGED
|
@@ -8,9 +8,16 @@ import { createState } from './create-state'
|
|
|
8
8
|
export const STATE_SCHEDULER = createScheduler()
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Create state
|
|
11
|
+
* Create a new state with an initial value and optional equality check
|
|
12
|
+
* @param initialValue The initial value or a function that returns the initial value
|
|
13
|
+
* @param isEqual Optional custom equality check function
|
|
14
|
+
* @returns A State<T> object
|
|
12
15
|
*/
|
|
13
16
|
export function create<T>(initialValue: DefaultValue<T>, isEqual: IsEqual<T> = isEqualBase): State<T> {
|
|
17
|
+
/**
|
|
18
|
+
* Get the current value of the state, initializing it if necessary.
|
|
19
|
+
* @returns The current value of the state
|
|
20
|
+
*/
|
|
14
21
|
function getValue(): T {
|
|
15
22
|
try {
|
|
16
23
|
if (isUndefined(state.cache.current)) {
|
|
@@ -28,6 +35,11 @@ export function create<T>(initialValue: DefaultValue<T>, isEqual: IsEqual<T> = i
|
|
|
28
35
|
return state.cache.current
|
|
29
36
|
}
|
|
30
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Handle async set value when previous value is promise and new value is function
|
|
40
|
+
* @param previousPromise Previous promise
|
|
41
|
+
* @param value New value function
|
|
42
|
+
*/
|
|
31
43
|
async function handleAsyncSetValue(previousPromise: Promise<T>, value: SetStateCb<T>) {
|
|
32
44
|
await previousPromise
|
|
33
45
|
const newValue = value(state.cache.current as Awaited<T>)
|
|
@@ -35,6 +47,10 @@ export function create<T>(initialValue: DefaultValue<T>, isEqual: IsEqual<T> = i
|
|
|
35
47
|
state.cache.current = resolvedValue
|
|
36
48
|
}
|
|
37
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Set value to state
|
|
52
|
+
* @param value Value to set
|
|
53
|
+
*/
|
|
38
54
|
function setValue(value: SetValue<T>) {
|
|
39
55
|
const previous = getValue()
|
|
40
56
|
const isFunctionValue = isSetValueFunction(value)
|
|
@@ -20,6 +20,10 @@ interface SendOptions {
|
|
|
20
20
|
value: unknown
|
|
21
21
|
name: string
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Send state information to Redux DevTools if available
|
|
25
|
+
* @param options Options containing message, type, value, and name
|
|
26
|
+
*/
|
|
23
27
|
function sendToDevelopmentTools(options: SendOptions) {
|
|
24
28
|
if (!reduxDevelopmentTools) {
|
|
25
29
|
return
|
|
@@ -31,12 +35,23 @@ function sendToDevelopmentTools(options: SendOptions) {
|
|
|
31
35
|
reduxDevelopmentTools.send(name, { value, type, message }, type)
|
|
32
36
|
}
|
|
33
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Create a listener function for development tools that sends state updates
|
|
40
|
+
* @param name The name of the state
|
|
41
|
+
* @param type The type of the state ('state' or 'derived')
|
|
42
|
+
* @returns A listener function that sends updates to development tools
|
|
43
|
+
*/
|
|
34
44
|
function developmentToolsListener(name: string, type: StateType) {
|
|
35
45
|
return (value: unknown) => {
|
|
36
46
|
sendToDevelopmentTools({ name, type, value, message: 'update' })
|
|
37
47
|
}
|
|
38
48
|
}
|
|
39
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Subscribe a state to development tools if available
|
|
52
|
+
* @param state The state to subscribe
|
|
53
|
+
* @returns A function to unsubscribe from development tools
|
|
54
|
+
*/
|
|
40
55
|
export function subscribeToDevelopmentTools<T>(state: State<T> | GetState<T>) {
|
|
41
56
|
if (process.env.NODE_ENV === 'production') {
|
|
42
57
|
return
|
package/src/scheduler.ts
CHANGED
|
@@ -27,6 +27,9 @@ export function createScheduler() {
|
|
|
27
27
|
let frame = performance.now()
|
|
28
28
|
let scheduled = false
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Schedule the next flush based on time and item count thresholds
|
|
32
|
+
*/
|
|
30
33
|
function schedule() {
|
|
31
34
|
const startFrame = performance.now()
|
|
32
35
|
const frameSizeDiffIn = startFrame - frame
|
|
@@ -47,6 +50,9 @@ export function createScheduler() {
|
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Flush the current batch of scheduled items
|
|
55
|
+
*/
|
|
50
56
|
function flush() {
|
|
51
57
|
if (batches.size === 0) {
|
|
52
58
|
return
|
package/src/select.ts
CHANGED
|
@@ -13,14 +13,23 @@ type AwaitedArray<T extends Array<unknown>> = {
|
|
|
13
13
|
[K in keyof T]: Awaited<T[K]>
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Create a derived state from multiple dependency states using a selector function
|
|
17
|
+
* @param states An array of dependency states
|
|
18
|
+
* @param selector A function that takes the values of the dependency states and returns a derived value
|
|
19
|
+
* @param isEqual Optional custom equality check function to prevent unnecessary updates
|
|
20
|
+
* @returns A GetState<T> representing the derived state
|
|
18
21
|
*/
|
|
19
22
|
export function select<T = unknown, S extends Array<unknown> = []>(
|
|
20
23
|
states: StateDependencies<S>,
|
|
21
24
|
selector: (...values: AwaitedArray<S>) => T,
|
|
22
25
|
isEqual?: IsEqual<T>,
|
|
23
26
|
): GetState<T> {
|
|
27
|
+
/**
|
|
28
|
+
* Compute the derived value based on the current values of the dependency states.
|
|
29
|
+
* If any dependency state is a promise, the result will be a promise that resolves
|
|
30
|
+
* once all dependencies are resolved.
|
|
31
|
+
* @returns The computed value or a promise that resolves to the computed value
|
|
32
|
+
*/
|
|
24
33
|
function computedValue(): T {
|
|
25
34
|
let hasPromise = false
|
|
26
35
|
const values = states.map((state) => {
|
|
@@ -47,6 +56,11 @@ export function select<T = unknown, S extends Array<unknown> = []>(
|
|
|
47
56
|
const result = selector(...(values as AwaitedArray<S>))
|
|
48
57
|
return result
|
|
49
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Get the current snapshot of the derived state.
|
|
61
|
+
* If the current cached value is undefined, it computes a new value.
|
|
62
|
+
* @returns The current snapshot value of the derived state
|
|
63
|
+
*/
|
|
50
64
|
function getSnapshot(): T {
|
|
51
65
|
if (isUndefined(state.cache.current)) {
|
|
52
66
|
const newValue = computedValue()
|
|
@@ -54,6 +68,12 @@ export function select<T = unknown, S extends Array<unknown> = []>(
|
|
|
54
68
|
}
|
|
55
69
|
return state.cache.current
|
|
56
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Get the current value of the derived state, initializing it if necessary.
|
|
73
|
+
* If the current cached value is a promise, it returns a new promise that resolves
|
|
74
|
+
* once the cached promise resolves, ensuring that undefined values are re-evaluated.
|
|
75
|
+
* @returns The current value of the derived state or a promise that resolves to it
|
|
76
|
+
*/
|
|
57
77
|
function getValue(): T {
|
|
58
78
|
if (isUndefined(state.cache.current)) {
|
|
59
79
|
const newValue = computedValue()
|
|
@@ -13,6 +13,10 @@ type SearchId = string
|
|
|
13
13
|
const STATE_SCHEDULER = createScheduler()
|
|
14
14
|
|
|
15
15
|
let stateId = 0
|
|
16
|
+
/**
|
|
17
|
+
* Get a unique state ID
|
|
18
|
+
* @returns The unique state ID
|
|
19
|
+
*/
|
|
16
20
|
function getStateId() {
|
|
17
21
|
return stateId++
|
|
18
22
|
}
|
|
@@ -50,13 +54,28 @@ interface DataItems<Document extends DocType> {
|
|
|
50
54
|
options?: SearchOptions<Document, unknown>
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Create a SyncTable that wraps a Table and provides reactive capabilities
|
|
59
|
+
* @param options Options to create the SyncTable, including the backend and table name
|
|
60
|
+
* @returns A SyncTable instance with methods to interact with the underlying Table and manage reactive searches
|
|
61
|
+
*/
|
|
53
62
|
export function createSqliteState<Document extends DocType>(options: CreateSqliteOptions<Document>): SyncTable<Document> {
|
|
54
63
|
const id = getStateId()
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get a unique schedule ID for a search ID
|
|
67
|
+
* @param searchId The search ID
|
|
68
|
+
* @returns The unique schedule ID
|
|
69
|
+
*/
|
|
55
70
|
function getScheduleId(searchId: SearchId) {
|
|
56
71
|
return `state-${id}-search-${searchId}`
|
|
57
72
|
}
|
|
58
73
|
|
|
59
74
|
let cachedTable: Table<Document> | undefined
|
|
75
|
+
/**
|
|
76
|
+
* Get or create the underlying table
|
|
77
|
+
* @returns The Table instance
|
|
78
|
+
*/
|
|
60
79
|
async function getTable() {
|
|
61
80
|
if (!cachedTable) {
|
|
62
81
|
const { backend, ...rest } = options
|
|
@@ -75,6 +94,12 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
75
94
|
const listeners = new Map<SearchId, () => void>()
|
|
76
95
|
const iterators = new Map<SearchId, AsyncIterableIterator<NextResult>>()
|
|
77
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Next step in the iterator
|
|
99
|
+
* @param searchId The search ID
|
|
100
|
+
* @param data The data items to process
|
|
101
|
+
* @returns boolean indicating if new items were added
|
|
102
|
+
*/
|
|
78
103
|
async function next(searchId: SearchId, data: DataItems<Document>): Promise<boolean> {
|
|
79
104
|
const iterator = iterators.get(searchId)
|
|
80
105
|
const { options = {} } = data
|
|
@@ -101,6 +126,10 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
101
126
|
return true
|
|
102
127
|
}
|
|
103
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Notify listeners of up dates
|
|
131
|
+
* @param searchId The search ID to notify
|
|
132
|
+
*/
|
|
104
133
|
function notifyListeners(searchId: SearchId) {
|
|
105
134
|
const searchListeners = listeners.get(searchId)
|
|
106
135
|
if (searchListeners) {
|
|
@@ -108,6 +137,10 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
108
137
|
}
|
|
109
138
|
}
|
|
110
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Refresh the cache for a search ID
|
|
142
|
+
* @param searchId The search ID to refresh
|
|
143
|
+
*/
|
|
111
144
|
async function refreshCache(searchId: SearchId) {
|
|
112
145
|
const table = await getTable()
|
|
113
146
|
const data = cachedData.get(searchId)
|
|
@@ -119,11 +152,20 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
119
152
|
data.items = []
|
|
120
153
|
await next(searchId, data)
|
|
121
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Refresh the data and notify listeners
|
|
157
|
+
* @param searchId The search ID to refresh
|
|
158
|
+
*/
|
|
122
159
|
async function refresh(searchId: SearchId) {
|
|
123
160
|
await refreshCache(searchId)
|
|
124
161
|
notifyListeners(searchId)
|
|
125
162
|
}
|
|
126
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Handle changes to the data
|
|
166
|
+
* @param mutationResult The mutation result
|
|
167
|
+
* @returns A set of search IDs that need to be updated
|
|
168
|
+
*/
|
|
127
169
|
function handleChange(mutationResult: MutationResult) {
|
|
128
170
|
const { key, op } = mutationResult
|
|
129
171
|
// find all cached data with key
|
|
@@ -147,6 +189,10 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
147
189
|
return searchIds
|
|
148
190
|
}
|
|
149
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Handle multiple changes
|
|
194
|
+
* @param mutationResults The array of mutation results
|
|
195
|
+
*/
|
|
150
196
|
async function handleChanges(mutationResults: MutationResult[]) {
|
|
151
197
|
const updateSearchIds = new Set<SearchId>()
|
|
152
198
|
for (const mutationResult of mutationResults) {
|
|
@@ -165,6 +211,12 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
165
211
|
|
|
166
212
|
const clearSchedulers = new Set<() => void>()
|
|
167
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Register data for a search ID
|
|
216
|
+
* @param searchId The search ID
|
|
217
|
+
* @param options Optional search options
|
|
218
|
+
* @returns The data items for the search ID
|
|
219
|
+
*/
|
|
168
220
|
function registerData(searchId: SearchId, options?: SearchOptions<Document, unknown>) {
|
|
169
221
|
if (!cachedData.has(searchId)) {
|
|
170
222
|
cachedData.set(searchId, { items: [], options, keys: new Set() })
|
package/src/sqlite/select-sql.ts
CHANGED
|
@@ -16,11 +16,21 @@ export interface SqlSeachOptions<Document extends DocType> {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
let stateId = 0
|
|
19
|
+
/**
|
|
20
|
+
* Generate a unique state ID
|
|
21
|
+
* @returns A unique state ID
|
|
22
|
+
*/
|
|
19
23
|
function getStateId() {
|
|
20
24
|
stateId++
|
|
21
25
|
return `${stateId.toString(36)}-sql`
|
|
22
26
|
}
|
|
23
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Create a state that derives its value from a SyncTable using a compute function
|
|
30
|
+
* @param state The SyncTable to derive from
|
|
31
|
+
* @param compute A function that takes parameters and returns SqlSeachOptions to filter the SyncTable
|
|
32
|
+
* @returns A function that takes parameters and returns a GetState of the derived documents
|
|
33
|
+
*/
|
|
24
34
|
export function selectSql<Document extends DocType, Params extends unknown[] = []>(
|
|
25
35
|
state: SyncTable<Document>,
|
|
26
36
|
compute: (...args: Params) => SqlSeachOptions<Document>,
|
|
@@ -2,9 +2,18 @@ import { Database, type Statement } from 'bun:sqlite'
|
|
|
2
2
|
import type { Backend } from './backend'
|
|
3
3
|
import { MapDeque } from './map-deque'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Create an in-memory SQLite backend using Bun's SQLite implementation
|
|
7
|
+
* @returns A Backend instance for in-memory SQLite operations
|
|
8
|
+
*/
|
|
5
9
|
export function bunMemoryBackend(): Backend {
|
|
6
10
|
const db = Database.open(':memory:')
|
|
7
11
|
const prepares = new MapDeque<string, Statement>(100)
|
|
12
|
+
/**
|
|
13
|
+
* Get or prepare a SQLite statement, caching it for future use
|
|
14
|
+
* @param query The SQL query string
|
|
15
|
+
* @returns The prepared SQLite statement
|
|
16
|
+
*/
|
|
8
17
|
function getStatement(query: string): Statement {
|
|
9
18
|
if (prepares.has(query)) {
|
|
10
19
|
return prepares.get(query)!
|
|
@@ -11,11 +11,21 @@ import { getWhereQuery } from './where'
|
|
|
11
11
|
const DELETE_IN_CHUNK = 500 // keep well below SQLite's default 999 parameter limit
|
|
12
12
|
export const DEFAULT_STEP_SIZE = 100
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Convert a dot-separated path to a JSON path
|
|
16
|
+
* @param dot The dot-separated path
|
|
17
|
+
* @returns The JSON path
|
|
18
|
+
*/
|
|
19
|
+
export function toJsonPath(dot: string) {
|
|
16
20
|
return '$.' + dot
|
|
17
21
|
}
|
|
18
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Get a nested value from an object using a dot-separated path
|
|
25
|
+
* @param object The object to get the value from
|
|
26
|
+
* @param path The dot-separated path to the value
|
|
27
|
+
* @returns The value at the specified path, or undefined if not found
|
|
28
|
+
*/
|
|
19
29
|
export function getByPath<T extends object>(object: T, path: string): unknown {
|
|
20
30
|
if (!object || !path) return undefined
|
|
21
31
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
@@ -27,6 +37,11 @@ export function getByPath<T extends object>(object: T, path: string): unknown {
|
|
|
27
37
|
}, object)
|
|
28
38
|
}
|
|
29
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Create a new table in the database with the given options
|
|
42
|
+
* @param options The options for creating the table
|
|
43
|
+
* @returns The created table
|
|
44
|
+
*/
|
|
30
45
|
export async function createTable<Document extends DocType>(options: DbOptions<Document>): Promise<Table<Document>> {
|
|
31
46
|
const { backend, tableName, indexes, key, disablePragmaOptimization } = options
|
|
32
47
|
const hasUserKey = key !== undefined
|
|
@@ -64,11 +79,21 @@ export async function createTable<Document extends DocType>(options: DbOptions<D
|
|
|
64
79
|
)
|
|
65
80
|
}
|
|
66
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Get the key value from a document
|
|
84
|
+
* @param document The document to extract the key from
|
|
85
|
+
* @returns The key value or undefined if no user key is configured
|
|
86
|
+
*/
|
|
67
87
|
function getKeyFromDocument(document: Document): Key | undefined {
|
|
68
88
|
if (!hasUserKey) return undefined
|
|
69
89
|
return getByPath(document, String(key)) as Key | undefined
|
|
70
90
|
}
|
|
71
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Get the number of rows changed by the last operation
|
|
94
|
+
* @param conn The database connection
|
|
95
|
+
* @returns The number of rows changed
|
|
96
|
+
*/
|
|
72
97
|
async function getChanges(conn: typeof backend): Promise<number> {
|
|
73
98
|
const r = await conn.select<Array<{ c: number }>>(`SELECT changes() AS c`)
|
|
74
99
|
return r[0]?.c ?? 0
|
|
@@ -34,9 +34,11 @@ export type Where<T extends Record<string, unknown>> =
|
|
|
34
34
|
readonly NOT?: Where<T>
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Inline a value for SQL query, with proper escaping for strings
|
|
39
|
+
* @param value The value to inline
|
|
40
|
+
* @returns The inlined value as a string
|
|
41
|
+
*/
|
|
40
42
|
function inlineValue(value: unknown): string {
|
|
41
43
|
if (typeof value === 'string') return `'${value.replaceAll("'", "''")}'`
|
|
42
44
|
if (typeof value === 'number') return value.toString()
|
|
@@ -44,6 +46,13 @@ function inlineValue(value: unknown): string {
|
|
|
44
46
|
return `'${String(value).replaceAll("'", "''")}'`
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Get SQL expression for a field, with proper casting based on value type
|
|
51
|
+
* @param field The field name
|
|
52
|
+
* @param value The field value
|
|
53
|
+
* @param tableAlias Optional table alias to prefix the field name
|
|
54
|
+
* @returns The SQL expression for the field
|
|
55
|
+
*/
|
|
47
56
|
function getFieldExpr(field: string, value: unknown, tableAlias?: string): string {
|
|
48
57
|
const prefix = tableAlias ? `${tableAlias}.` : ''
|
|
49
58
|
if (field === 'KEY') {
|
|
@@ -57,9 +66,12 @@ function getFieldExpr(field: string, value: unknown, tableAlias?: string): strin
|
|
|
57
66
|
|
|
58
67
|
const OPS_SET: ReadonlySet<string> = new Set(['is', 'isNot', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn', 'like'])
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Flatten a nested Where object into a single-level object with dot-separated keys
|
|
71
|
+
* @param object The nested Where object
|
|
72
|
+
* @param prefix The prefix for the current recursion level (used internally)
|
|
73
|
+
* @returns A flattened object with dot-separated keys
|
|
74
|
+
*/
|
|
63
75
|
function flattenWhere(object: Record<string, unknown>, prefix = ''): Record<string, unknown> {
|
|
64
76
|
const result: Record<string, unknown> = {}
|
|
65
77
|
|
|
@@ -81,9 +93,12 @@ function flattenWhere(object: Record<string, unknown>, prefix = ''): Record<stri
|
|
|
81
93
|
return result
|
|
82
94
|
}
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Write SQL WHERE clause from a Where object
|
|
98
|
+
* @param where The Where object defining the conditions
|
|
99
|
+
* @param tableAlias Optional table alias to prefix field names
|
|
100
|
+
* @returns The SQL WHERE clause string (without the "WHERE" keyword)
|
|
101
|
+
*/
|
|
87
102
|
export function getWhere<T extends Record<string, unknown>>(where: Where<T>, tableAlias?: string): string {
|
|
88
103
|
if (!where || typeof where !== 'object') return ''
|
|
89
104
|
|
|
@@ -172,9 +187,11 @@ export function getWhere<T extends Record<string, unknown>>(where: Where<T>, tab
|
|
|
172
187
|
return anyField ? `(${fieldClauses})` : ''
|
|
173
188
|
}
|
|
174
189
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Get SQL WHERE clause from a Where object
|
|
192
|
+
* @param where The Where object defining the conditions
|
|
193
|
+
* @returns The SQL WHERE clause string (without the "WHERE" keyword)
|
|
194
|
+
*/
|
|
178
195
|
export function getWhereQuery<T extends Record<string, unknown>>(where?: Where<T>): string {
|
|
179
196
|
if (!where) return ''
|
|
180
197
|
const clause = getWhere(where)
|
package/src/sqlite/use-sqlite.ts
CHANGED
|
@@ -17,6 +17,14 @@ export interface UseSearchOptions<Document extends DocType, Selected = Document>
|
|
|
17
17
|
readonly select?: (document: Document) => Selected
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* React hook to subscribe to a SyncTable and get its current snapshot, with optional search options and selector for derived state
|
|
22
|
+
* @param state The SyncTable to subscribe to
|
|
23
|
+
* @param options Optional search options to filter and sort the documents
|
|
24
|
+
* @param deps Dependency list to control when to update the search options
|
|
25
|
+
* @returns A tuple containing the current array of documents (or selected documents) and an object with actions to interact with the SyncTable
|
|
26
|
+
* @throws If the value is a Promise or an Error, it will be thrown to be handled by an error boundary or suspense
|
|
27
|
+
*/
|
|
20
28
|
export function useSqliteValue<Document extends DocType, Selected = Document>(
|
|
21
29
|
state: SyncTable<Document>,
|
|
22
30
|
options: UseSearchOptions<Document, Selected> = {},
|
package/src/use-value.ts
CHANGED
|
@@ -3,6 +3,13 @@ import { EMPTY_SELECTOR, type GetState } from './types'
|
|
|
3
3
|
import { isError, isPromise } from './utils/is'
|
|
4
4
|
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* React hook to subscribe to a state and get its value, with optional selector for derived state
|
|
8
|
+
* @param state The state to subscribe to
|
|
9
|
+
* @param selector Optional function to derive a value from the state
|
|
10
|
+
* @returns The current value of the state or the derived value from the selector
|
|
11
|
+
* @throws If the value is a Promise or an Error, it will be thrown to be handled by an error boundary or suspense
|
|
12
|
+
*/
|
|
6
13
|
export function useValue<T, S>(
|
|
7
14
|
state: GetState<T>,
|
|
8
15
|
selector: (stateValue: Awaited<T>) => S = EMPTY_SELECTOR,
|
package/src/utils/common.ts
CHANGED
|
@@ -11,6 +11,9 @@ export class AbortError extends Error {
|
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Cancelable promise function, return promise and controller
|
|
14
|
+
* @param promise Original promise
|
|
15
|
+
* @param previousController Previous AbortController to abort if exists
|
|
16
|
+
* @returns CancelablePromise<T>
|
|
14
17
|
*/
|
|
15
18
|
export function cancelablePromise<T>(promise: Promise<T>, previousController?: AbortController): CancelablePromise<T> {
|
|
16
19
|
if (previousController) {
|
|
@@ -32,6 +35,10 @@ export function cancelablePromise<T>(promise: Promise<T>, previousController?: A
|
|
|
32
35
|
|
|
33
36
|
/**
|
|
34
37
|
* Check if the cache value is different from the previous value.
|
|
38
|
+
* If they are the same, return false to avoid unnecessary updates.
|
|
39
|
+
* @param cache - The cache object containing current and previous values
|
|
40
|
+
* @param isEqual - Optional custom equality check function
|
|
41
|
+
* @returns boolean indicating whether an update should occur
|
|
35
42
|
*/
|
|
36
43
|
export function canUpdate<T>(cache: Cache<T>, isEqual: IsEqual<T> = isEqualBase): boolean {
|
|
37
44
|
if (!isUndefined(cache.current)) {
|
|
@@ -45,6 +52,9 @@ export function canUpdate<T>(cache: Cache<T>, isEqual: IsEqual<T> = isEqualBase)
|
|
|
45
52
|
|
|
46
53
|
/**
|
|
47
54
|
* Handle async updates for `create` and `select`
|
|
55
|
+
* @param state - state object
|
|
56
|
+
* @param value - new value
|
|
57
|
+
* @returns T or Promise<T>
|
|
48
58
|
*/
|
|
49
59
|
export function handleAsyncUpdate<T>(state: State<T>, value: T): T {
|
|
50
60
|
const {
|
|
@@ -15,8 +15,9 @@ export interface Emitter<T, P = undefined> {
|
|
|
15
15
|
* T: Type of the state
|
|
16
16
|
* R: Type of the snapshot
|
|
17
17
|
* P: Type of the parameters
|
|
18
|
-
* @param getSnapshot
|
|
19
|
-
* @
|
|
18
|
+
* @param getSnapshot Function to get the current snapshot
|
|
19
|
+
* @param getInitialSnapshot Optional function to get the initial snapshot
|
|
20
|
+
* @returns An emitter object with methods to manage listeners and emit events
|
|
20
21
|
*/
|
|
21
22
|
export function createEmitter<T, P = undefined>(getSnapshot: () => T, getInitialSnapshot?: () => T): Emitter<T, P> {
|
|
22
23
|
const listeners = new Set<(...params: P[]) => void>()
|
package/src/utils/is.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable jsdoc/require-jsdoc */
|
|
1
2
|
import type { SetStateCb, SetValue, State } from '../types'
|
|
2
3
|
import { AbortError } from './common'
|
|
3
4
|
|
|
@@ -27,9 +28,11 @@ export function isEqualBase<T>(valueA: T, valueB: T): boolean {
|
|
|
27
28
|
}
|
|
28
29
|
return !!Object.is(valueA, valueB)
|
|
29
30
|
}
|
|
31
|
+
|
|
30
32
|
export function isSetValueFunction<T>(value: SetValue<T>): value is SetStateCb<T> {
|
|
31
33
|
return typeof value === 'function'
|
|
32
34
|
}
|
|
35
|
+
|
|
33
36
|
export function isAbortError(value: unknown): value is AbortError {
|
|
34
37
|
return value instanceof AbortError
|
|
35
38
|
}
|
package/src/utils/shallow.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
/* eslint-disable sonarjs/cognitive-complexity */
|
|
2
2
|
import { isArray, isMap, isSet } from './is'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Performs a shallow comparison between two values to determine if they are equivalent.
|
|
6
|
+
* This function checks if the two values are the same reference, or if they are objects,
|
|
7
|
+
* @param valueA The first value to compare.
|
|
8
|
+
* @param valueB The second value to compare.
|
|
9
|
+
* @returns True if the values are shallowly equal, false otherwise.
|
|
10
|
+
*/
|
|
4
11
|
export function shallow<T>(valueA: T, valueB: T): boolean {
|
|
5
12
|
if (valueA == valueB) {
|
|
6
13
|
return true
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { Component } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Create a promise that resolves after a specified time
|
|
4
|
+
* @param time Time in ms to wait
|
|
5
|
+
* @returns A promise that resolves after the specified time
|
|
6
|
+
*/
|
|
2
7
|
export declare function longPromise(time?: number): Promise<number>;
|
|
3
8
|
export declare class ErrorBoundary extends Component<{
|
|
4
9
|
fallback: React.ReactNode;
|
package/types/create-state.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ interface GetStateOptions<T> {
|
|
|
8
8
|
type FullState<T> = GetStateOptions<T>['set'] extends undefined ? GetState<T> : State<T>;
|
|
9
9
|
/**
|
|
10
10
|
* This is just utility function to create state base data
|
|
11
|
+
* @param options Options to create state
|
|
12
|
+
* @returns FullState<T>
|
|
11
13
|
*/
|
|
12
14
|
export declare function createState<T>(options: GetStateOptions<T>): FullState<T>;
|
|
13
15
|
export {};
|
package/types/create.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export declare const STATE_SCHEDULER: {
|
|
|
4
4
|
schedule<T>(id: string | number | symbol, value: T): void;
|
|
5
5
|
};
|
|
6
6
|
/**
|
|
7
|
-
* Create state
|
|
7
|
+
* Create a new state with an initial value and optional equality check
|
|
8
|
+
* @param initialValue The initial value or a function that returns the initial value
|
|
9
|
+
* @param isEqual Optional custom equality check function
|
|
10
|
+
* @returns A State<T> object
|
|
8
11
|
*/
|
|
9
12
|
export declare function create<T>(initialValue: DefaultValue<T>, isEqual?: IsEqual<T>): State<T>;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import type { GetState, State } from '../types';
|
|
2
2
|
export type StateType = 'state' | 'derived';
|
|
3
|
+
/**
|
|
4
|
+
* Subscribe a state to development tools if available
|
|
5
|
+
* @param state The state to subscribe
|
|
6
|
+
* @returns A function to unsubscribe from development tools
|
|
7
|
+
*/
|
|
3
8
|
export declare function subscribeToDevelopmentTools<T>(state: State<T> | GetState<T>): (() => void) | undefined;
|
package/types/select.d.ts
CHANGED
|
@@ -6,8 +6,11 @@ type AwaitedArray<T extends Array<unknown>> = {
|
|
|
6
6
|
[K in keyof T]: Awaited<T[K]>;
|
|
7
7
|
};
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Create a derived state from multiple dependency states using a selector function
|
|
10
|
+
* @param states An array of dependency states
|
|
11
|
+
* @param selector A function that takes the values of the dependency states and returns a derived value
|
|
12
|
+
* @param isEqual Optional custom equality check function to prevent unnecessary updates
|
|
13
|
+
* @returns A GetState<T> representing the derived state
|
|
11
14
|
*/
|
|
12
15
|
export declare function select<T = unknown, S extends Array<unknown> = []>(states: StateDependencies<S>, selector: (...values: AwaitedArray<S>) => T, isEqual?: IsEqual<T>): GetState<T>;
|
|
13
16
|
export {};
|
|
@@ -24,5 +24,10 @@ export interface SyncTable<Document extends DocType> {
|
|
|
24
24
|
readonly next: (searchId: SearchId) => Promise<boolean>;
|
|
25
25
|
readonly select: <Params extends unknown[]>(compute: (...args: Params) => SearchOptions<Document>) => CreateState<Document, Params>;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Create a SyncTable that wraps a Table and provides reactive capabilities
|
|
29
|
+
* @param options Options to create the SyncTable, including the backend and table name
|
|
30
|
+
* @returns A SyncTable instance with methods to interact with the underlying Table and manage reactive searches
|
|
31
|
+
*/
|
|
27
32
|
export declare function createSqliteState<Document extends DocType>(options: CreateSqliteOptions<Document>): SyncTable<Document>;
|
|
28
33
|
export {};
|
|
@@ -11,4 +11,10 @@ export interface SqlSeachOptions<Document extends DocType> {
|
|
|
11
11
|
readonly where?: Where<Document>;
|
|
12
12
|
readonly stepSize?: number;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a state that derives its value from a SyncTable using a compute function
|
|
16
|
+
* @param state The SyncTable to derive from
|
|
17
|
+
* @param compute A function that takes parameters and returns SqlSeachOptions to filter the SyncTable
|
|
18
|
+
* @returns A function that takes parameters and returns a GetState of the derived documents
|
|
19
|
+
*/
|
|
14
20
|
export declare function selectSql<Document extends DocType, Params extends unknown[] = []>(state: SyncTable<Document>, compute: (...args: Params) => SqlSeachOptions<Document>): CreateState<Document, Params>;
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import type { Table, DbOptions, DocType } from './table.types';
|
|
2
2
|
export declare const DEFAULT_STEP_SIZE = 100;
|
|
3
|
+
/**
|
|
4
|
+
* Convert a dot-separated path to a JSON path
|
|
5
|
+
* @param dot The dot-separated path
|
|
6
|
+
* @returns The JSON path
|
|
7
|
+
*/
|
|
8
|
+
export declare function toJsonPath(dot: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Get a nested value from an object using a dot-separated path
|
|
11
|
+
* @param object The object to get the value from
|
|
12
|
+
* @param path The dot-separated path to the value
|
|
13
|
+
* @returns The value at the specified path, or undefined if not found
|
|
14
|
+
*/
|
|
3
15
|
export declare function getByPath<T extends object>(object: T, path: string): unknown;
|
|
16
|
+
/**
|
|
17
|
+
* Create a new table in the database with the given options
|
|
18
|
+
* @param options The options for creating the table
|
|
19
|
+
* @returns The created table
|
|
20
|
+
*/
|
|
4
21
|
export declare function createTable<Document extends DocType>(options: DbOptions<Document>): Promise<Table<Document>>;
|
|
@@ -16,6 +16,17 @@ export type Where<T extends Record<string, unknown>> = {
|
|
|
16
16
|
readonly OR?: Array<Where<T>>;
|
|
17
17
|
readonly NOT?: Where<T>;
|
|
18
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* Write SQL WHERE clause from a Where object
|
|
21
|
+
* @param where The Where object defining the conditions
|
|
22
|
+
* @param tableAlias Optional table alias to prefix field names
|
|
23
|
+
* @returns The SQL WHERE clause string (without the "WHERE" keyword)
|
|
24
|
+
*/
|
|
19
25
|
export declare function getWhere<T extends Record<string, unknown>>(where: Where<T>, tableAlias?: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Get SQL WHERE clause from a Where object
|
|
28
|
+
* @param where The Where object defining the conditions
|
|
29
|
+
* @returns The SQL WHERE clause string (without the "WHERE" keyword)
|
|
30
|
+
*/
|
|
20
31
|
export declare function getWhereQuery<T extends Record<string, unknown>>(where?: Where<T>): string;
|
|
21
32
|
export {};
|
|
@@ -12,4 +12,12 @@ export interface UseSearchOptions<Document extends DocType, Selected = Document>
|
|
|
12
12
|
*/
|
|
13
13
|
readonly select?: (document: Document) => Selected;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* React hook to subscribe to a SyncTable and get its current snapshot, with optional search options and selector for derived state
|
|
17
|
+
* @param state The SyncTable to subscribe to
|
|
18
|
+
* @param options Optional search options to filter and sort the documents
|
|
19
|
+
* @param deps Dependency list to control when to update the search options
|
|
20
|
+
* @returns A tuple containing the current array of documents (or selected documents) and an object with actions to interact with the SyncTable
|
|
21
|
+
* @throws If the value is a Promise or an Error, it will be thrown to be handled by an error boundary or suspense
|
|
22
|
+
*/
|
|
15
23
|
export declare function useSqliteValue<Document extends DocType, Selected = Document>(state: SyncTable<Document>, options?: UseSearchOptions<Document, Selected>, deps?: DependencyList): [undefined extends Selected ? Document[] : Selected[], SqLiteActions];
|
package/types/use-value.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
import { type GetState } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* React hook to subscribe to a state and get its value, with optional selector for derived state
|
|
4
|
+
* @param state The state to subscribe to
|
|
5
|
+
* @param selector Optional function to derive a value from the state
|
|
6
|
+
* @returns The current value of the state or the derived value from the selector
|
|
7
|
+
* @throws If the value is a Promise or an Error, it will be thrown to be handled by an error boundary or suspense
|
|
8
|
+
*/
|
|
2
9
|
export declare function useValue<T, S>(state: GetState<T>, selector?: (stateValue: Awaited<T>) => S): undefined extends S ? Awaited<T> : S;
|
package/types/utils/common.d.ts
CHANGED
|
@@ -8,13 +8,23 @@ export declare class AbortError extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Cancelable promise function, return promise and controller
|
|
11
|
+
* @param promise Original promise
|
|
12
|
+
* @param previousController Previous AbortController to abort if exists
|
|
13
|
+
* @returns CancelablePromise<T>
|
|
11
14
|
*/
|
|
12
15
|
export declare function cancelablePromise<T>(promise: Promise<T>, previousController?: AbortController): CancelablePromise<T>;
|
|
13
16
|
/**
|
|
14
17
|
* Check if the cache value is different from the previous value.
|
|
18
|
+
* If they are the same, return false to avoid unnecessary updates.
|
|
19
|
+
* @param cache - The cache object containing current and previous values
|
|
20
|
+
* @param isEqual - Optional custom equality check function
|
|
21
|
+
* @returns boolean indicating whether an update should occur
|
|
15
22
|
*/
|
|
16
23
|
export declare function canUpdate<T>(cache: Cache<T>, isEqual?: IsEqual<T>): boolean;
|
|
17
24
|
/**
|
|
18
25
|
* Handle async updates for `create` and `select`
|
|
26
|
+
* @param state - state object
|
|
27
|
+
* @param value - new value
|
|
28
|
+
* @returns T or Promise<T>
|
|
19
29
|
*/
|
|
20
30
|
export declare function handleAsyncUpdate<T>(state: State<T>, value: T): T;
|
|
@@ -14,7 +14,8 @@ export interface Emitter<T, P = undefined> {
|
|
|
14
14
|
* T: Type of the state
|
|
15
15
|
* R: Type of the snapshot
|
|
16
16
|
* P: Type of the parameters
|
|
17
|
-
* @param getSnapshot
|
|
18
|
-
* @
|
|
17
|
+
* @param getSnapshot Function to get the current snapshot
|
|
18
|
+
* @param getInitialSnapshot Optional function to get the initial snapshot
|
|
19
|
+
* @returns An emitter object with methods to manage listeners and emit events
|
|
19
20
|
*/
|
|
20
21
|
export declare function createEmitter<T, P = undefined>(getSnapshot: () => T, getInitialSnapshot?: () => T): Emitter<T, P>;
|
package/types/utils/shallow.d.ts
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performs a shallow comparison between two values to determine if they are equivalent.
|
|
3
|
+
* This function checks if the two values are the same reference, or if they are objects,
|
|
4
|
+
* @param valueA The first value to compare.
|
|
5
|
+
* @param valueB The second value to compare.
|
|
6
|
+
* @returns True if the values are shallowly equal, false otherwise.
|
|
7
|
+
*/
|
|
1
8
|
export declare function shallow<T>(valueA: T, valueB: T): boolean;
|