@anfenn/dync 1.0.18 → 1.0.20
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/README.md +2 -0
- package/dist/{chunk-WZ7V4U6Z.js → chunk-I2KQD4DD.js} +35 -23
- package/dist/chunk-I2KQD4DD.js.map +1 -0
- package/dist/index.cjs +34 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.js +1 -1
- package/package.json +1 -1
- package/src/storage/sqlite/SQLiteCollection.ts +19 -13
- package/src/storage/sqlite/helpers.ts +21 -9
- package/src/storage/sqlite/types.ts +5 -2
- package/dist/chunk-WZ7V4U6Z.js.map +0 -1
package/dist/index.js
CHANGED
package/dist/react/index.js
CHANGED
package/package.json
CHANGED
|
@@ -14,20 +14,21 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
14
14
|
this.state = {
|
|
15
15
|
...base,
|
|
16
16
|
...state,
|
|
17
|
-
|
|
17
|
+
orGroups: state?.orGroups ?? base.orGroups,
|
|
18
18
|
jsPredicate: state?.jsPredicate,
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
getState(): SQLiteCollectionState<T> {
|
|
23
|
-
return { ...this.state,
|
|
23
|
+
return { ...this.state, orGroups: this.state.orGroups.map((g) => [...g]) };
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// Add a SQL-expressible condition to
|
|
26
|
+
// Add a SQL-expressible condition to the current OR group
|
|
27
27
|
addSqlCondition(condition: SQLiteCondition): SQLiteCollection<T> {
|
|
28
|
+
const newGroups = this.state.orGroups.map((g, i) => (i === this.state.orGroups.length - 1 ? [...g, condition] : g));
|
|
28
29
|
return new SQLiteCollection(this.table, {
|
|
29
30
|
...this.state,
|
|
30
|
-
|
|
31
|
+
orGroups: newGroups,
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -35,7 +36,7 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
35
36
|
return new SQLiteCollection(this.table, {
|
|
36
37
|
...this.state,
|
|
37
38
|
...overrides,
|
|
38
|
-
|
|
39
|
+
orGroups: overrides?.orGroups ?? this.state.orGroups,
|
|
39
40
|
jsPredicate: overrides?.jsPredicate !== undefined ? overrides.jsPredicate : this.state.jsPredicate,
|
|
40
41
|
});
|
|
41
42
|
}
|
|
@@ -73,7 +74,7 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
73
74
|
orderByOverride?: { index: string | string[]; direction: 'asc' | 'desc' };
|
|
74
75
|
} = {},
|
|
75
76
|
): Promise<TableEntry<T>[]> {
|
|
76
|
-
const { whereClause, parameters } = buildWhereClause(this.state.
|
|
77
|
+
const { whereClause, parameters } = buildWhereClause(this.state.orGroups);
|
|
77
78
|
const ordering = options.orderByOverride ?? this.resolveOrdering();
|
|
78
79
|
const cloneValues = options.clone !== false;
|
|
79
80
|
const hasJsFilter = this.hasJsPredicate();
|
|
@@ -160,7 +161,7 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
160
161
|
async keys(): Promise<unknown[]> {
|
|
161
162
|
// Optimization: use native SQL when no JS filtering needed
|
|
162
163
|
if (!this.hasJsPredicate()) {
|
|
163
|
-
const { whereClause, parameters } = buildWhereClause(this.state.
|
|
164
|
+
const { whereClause, parameters } = buildWhereClause(this.state.orGroups);
|
|
164
165
|
const ordering = this.resolveOrdering();
|
|
165
166
|
return this.table.queryKeysWithConditions({
|
|
166
167
|
whereClause,
|
|
@@ -183,7 +184,7 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
183
184
|
async uniqueKeys(): Promise<unknown[]> {
|
|
184
185
|
// Optimization: use native SQL DISTINCT when no JS filtering needed
|
|
185
186
|
if (!this.hasJsPredicate()) {
|
|
186
|
-
const { whereClause, parameters } = buildWhereClause(this.state.
|
|
187
|
+
const { whereClause, parameters } = buildWhereClause(this.state.orGroups);
|
|
187
188
|
const ordering = this.resolveOrdering();
|
|
188
189
|
return this.table.queryKeysWithConditions({
|
|
189
190
|
whereClause,
|
|
@@ -203,8 +204,8 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
203
204
|
// Optimization: use SQL COUNT when no JS filtering needed
|
|
204
205
|
if (!this.hasJsPredicate()) {
|
|
205
206
|
return this.table.countWithConditions({
|
|
206
|
-
whereClause: buildWhereClause(this.state.
|
|
207
|
-
parameters: buildWhereClause(this.state.
|
|
207
|
+
whereClause: buildWhereClause(this.state.orGroups).whereClause,
|
|
208
|
+
parameters: buildWhereClause(this.state.orGroups).parameters,
|
|
208
209
|
distinct: this.state.distinct,
|
|
209
210
|
});
|
|
210
211
|
}
|
|
@@ -229,7 +230,12 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
229
230
|
}
|
|
230
231
|
|
|
231
232
|
or(index: string): StorageWhereClause<T> {
|
|
232
|
-
|
|
233
|
+
// Start a new OR group - subsequent conditions will be ORed with previous groups
|
|
234
|
+
const newCollection = new SQLiteCollection(this.table, {
|
|
235
|
+
...this.state,
|
|
236
|
+
orGroups: [...this.state.orGroups, []],
|
|
237
|
+
});
|
|
238
|
+
return this.table.createWhereClause(index, newCollection);
|
|
233
239
|
}
|
|
234
240
|
|
|
235
241
|
clone(_props?: Record<string, unknown>): StorageCollection<T> {
|
|
@@ -255,7 +261,7 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
255
261
|
async delete(): Promise<number> {
|
|
256
262
|
// Optimization: use native SQL DELETE when no JS filtering needed
|
|
257
263
|
if (!this.hasJsPredicate()) {
|
|
258
|
-
const { whereClause, parameters } = buildWhereClause(this.state.
|
|
264
|
+
const { whereClause, parameters } = buildWhereClause(this.state.orGroups);
|
|
259
265
|
return this.table.deleteWithConditions({ whereClause, parameters });
|
|
260
266
|
}
|
|
261
267
|
// Fallback for JS filtering - must iterate and delete one by one
|
|
@@ -269,7 +275,7 @@ export class SQLiteCollection<T = any> implements StorageCollection<T> {
|
|
|
269
275
|
async modify(changes: Partial<T> | ((item: T) => void | Promise<void>)): Promise<number> {
|
|
270
276
|
// Optimization: use native SQL UPDATE when changes is an object and no JS filtering
|
|
271
277
|
if (typeof changes !== 'function' && !this.hasJsPredicate()) {
|
|
272
|
-
const { whereClause, parameters } = buildWhereClause(this.state.
|
|
278
|
+
const { whereClause, parameters } = buildWhereClause(this.state.orGroups);
|
|
273
279
|
return this.table.updateWithConditions({ whereClause, parameters, changes });
|
|
274
280
|
}
|
|
275
281
|
// Fallback for function-based changes or JS filtering
|
|
@@ -4,7 +4,7 @@ export const SQLITE_SCHEMA_VERSION_STATE_KEY = 'sqlite_schema_version';
|
|
|
4
4
|
export const DEFAULT_STREAM_BATCH_SIZE = 200;
|
|
5
5
|
|
|
6
6
|
export const createDefaultState = <T>(): SQLiteCollectionState<T> => ({
|
|
7
|
-
|
|
7
|
+
orGroups: [[]],
|
|
8
8
|
jsPredicate: undefined,
|
|
9
9
|
orderBy: undefined,
|
|
10
10
|
reverse: false,
|
|
@@ -18,22 +18,34 @@ export interface SQLiteBuiltQuery {
|
|
|
18
18
|
parameters: unknown[];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export const buildWhereClause = (
|
|
22
|
-
|
|
21
|
+
export const buildWhereClause = (orGroups: SQLiteCondition[][]): SQLiteBuiltQuery => {
|
|
22
|
+
// Filter out empty groups
|
|
23
|
+
const nonEmptyGroups = orGroups.filter((group) => group.length > 0);
|
|
24
|
+
|
|
25
|
+
if (nonEmptyGroups.length === 0) {
|
|
23
26
|
return { whereClause: '', parameters: [] };
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
const
|
|
29
|
+
const groupClauses: string[] = [];
|
|
27
30
|
const parameters: unknown[] = [];
|
|
28
31
|
|
|
29
|
-
for (const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
for (const group of nonEmptyGroups) {
|
|
33
|
+
const conditionClauses: string[] = [];
|
|
34
|
+
for (const condition of group) {
|
|
35
|
+
const built = buildCondition(condition);
|
|
36
|
+
conditionClauses.push(built.clause);
|
|
37
|
+
parameters.push(...built.parameters);
|
|
38
|
+
}
|
|
39
|
+
// AND conditions within a group
|
|
40
|
+
const groupClause = conditionClauses.length === 1 ? conditionClauses[0]! : `(${conditionClauses.join(' AND ')})`;
|
|
41
|
+
groupClauses.push(groupClause);
|
|
33
42
|
}
|
|
34
43
|
|
|
44
|
+
// OR between groups (wrap in parens if multiple groups)
|
|
45
|
+
const whereContent = groupClauses.length === 1 ? groupClauses[0]! : `(${groupClauses.join(' OR ')})`;
|
|
46
|
+
|
|
35
47
|
return {
|
|
36
|
-
whereClause: `WHERE ${
|
|
48
|
+
whereClause: `WHERE ${whereContent}`,
|
|
37
49
|
parameters,
|
|
38
50
|
};
|
|
39
51
|
};
|
|
@@ -79,8 +79,11 @@ export type SQLiteCondition =
|
|
|
79
79
|
| SQLiteConditionOr;
|
|
80
80
|
|
|
81
81
|
export interface SQLiteCollectionState<T> {
|
|
82
|
-
/**
|
|
83
|
-
|
|
82
|
+
/**
|
|
83
|
+
* OR groups of SQL conditions. Each group's conditions are ANDed together,
|
|
84
|
+
* then groups are ORed: (A AND B) OR (C) OR (D AND E)
|
|
85
|
+
*/
|
|
86
|
+
orGroups: SQLiteCondition[][];
|
|
84
87
|
/** JavaScript predicate for conditions that can't be expressed in SQL (e.g., arbitrary filter functions) */
|
|
85
88
|
jsPredicate?: (record: T, key: string, index: number) => boolean;
|
|
86
89
|
orderBy?: { index: string | string[]; direction: 'asc' | 'desc' };
|