Skip to content

Commit

Permalink
Merge pull request #18 from readwiseio/johannes/support-deleted-queries
Browse files Browse the repository at this point in the history
Support _deleted selector in RxDB queries
  • Loading branch information
jhlabs authored Oct 18, 2024
2 parents ade621a + d89783a commit 7ff705b
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 17 deletions.
28 changes: 28 additions & 0 deletions dist/cjs/rx-query-helper.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/cjs/rx-query-helper.js.map

Large diffs are not rendered by default.

25 changes: 21 additions & 4 deletions dist/cjs/rx-query.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/cjs/rx-query.js.map

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions dist/esm/rx-query-helper.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/esm/rx-query-helper.js.map

Large diffs are not rendered by default.

27 changes: 22 additions & 5 deletions dist/esm/rx-query.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/esm/rx-query.js.map

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion dist/types/rx-query-helper.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DeterministicSortComparator, FilledMangoQuery, MangoQuery, QueryMatcher, RxDocument, RxDocumentData, RxJsonSchema, RxQuery } from './types/index.d.ts';
import type { DeterministicSortComparator, FilledMangoQuery, MangoQuery, MangoQuerySelector, QueryMatcher, RxDocument, RxDocumentData, RxJsonSchema, RxQuery } from './types/index.d.ts';
/**
* Normalize the query to ensure we have all fields set
* and queries that represent the same query logic are detected as equal by the caching.
Expand All @@ -17,3 +17,9 @@ export declare function getSortComparator<RxDocType>(schema: RxJsonSchema<RxDocu
*/
export declare function getQueryMatcher<RxDocType>(_schema: RxJsonSchema<RxDocType> | RxJsonSchema<RxDocumentData<RxDocType>>, query: FilledMangoQuery<RxDocType>): QueryMatcher<RxDocumentData<RxDocType>>;
export declare function runQueryUpdateFunction<RxDocType, RxQueryResult>(rxQuery: RxQuery<RxDocType, RxQueryResult>, fn: (doc: RxDocument<RxDocType>) => Promise<RxDocument<RxDocType>>): Promise<RxQueryResult>;
/**
* Checks if a given selector includes deleted documents.
* @param selector The MangoQuerySelector to check
* @returns True if the selector includes deleted documents, false otherwise
*/
export declare function selectorIncludesDeleted<RxDocType>(selector: MangoQuerySelector<RxDocType> | undefined): boolean;
1 change: 1 addition & 0 deletions dist/types/rx-query.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export declare class RxQueryBase<RxDocType, RxQueryResult, OrmMethods = {}, Reac
constructor(op: RxQueryOP, mangoQuery: Readonly<MangoQuery<RxDocType>>, collection: RxCollection<RxDocType>, other?: any);
get $(): BehaviorSubject<RxQueryResult>;
get $$(): Reactivity;
get includesDeleted(): boolean;
_latestChangeEvent: -1 | number;
_lastExecStart: number;
_lastExecEnd: number;
Expand Down
1 change: 1 addition & 0 deletions examples/vite-vanilla-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"test:e2e": "testcafe chrome -e test/ --hostname localhost --selector-timeout 8000 --retry-test-pages"
},
"devDependencies": {
"@swc/core": "1.6.0",
"async-test-util": "2.5.0",
"concurrently": "8.2.2",
"copyfiles": "2.4.1",
Expand Down
61 changes: 61 additions & 0 deletions src/rx-query-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import type {
DeterministicSortComparator,
FilledMangoQuery,
MangoQuery,
MangoQueryOperators,
MangoQuerySelector,
MangoQuerySortDirection,
PropertyType,
QueryMatcher,
RxDocument,
RxDocumentData,
Expand Down Expand Up @@ -248,3 +251,61 @@ export async function runQueryUpdateFunction<RxDocType, RxQueryResult>(
return result as any;
}
}

/**
* Checks if a given selector includes deleted documents.
* @param selector The MangoQuerySelector to check
* @returns True if the selector includes deleted documents, false otherwise
*/
export function selectorIncludesDeleted<RxDocType>(
selector: MangoQuerySelector<RxDocType> | undefined
): boolean {
if (!selector) {
return false;
}

const isTrue = (value: unknown): boolean =>
value === true ||
(typeof value === 'object' &&
value !== null &&
'$eq' in value &&
(value as MangoQueryOperators<boolean>).$eq === true);


const isNotFalse = (value: unknown): boolean =>
value === true ||
(typeof value === 'object' &&
value !== null &&
'$ne' in value &&
(value as MangoQueryOperators<boolean>).$ne === false);

const hasDeletedTrue = (
condition: MangoQuerySelector<RxDocType>
): boolean =>
'_deleted' in condition &&
(isTrue(condition._deleted as PropertyType<RxDocType, '_deleted'>) ||
isNotFalse(
condition._deleted as PropertyType<RxDocType, '_deleted'>
));

if ('_deleted' in selector) {
return (
isTrue(selector._deleted as PropertyType<RxDocType, '_deleted'>) ||
isNotFalse(selector._deleted as PropertyType<RxDocType, '_deleted'>)
);
}

if ('$or' in selector && Array.isArray(selector.$or)) {
return selector.$or.some(hasDeletedTrue);
}

if ('$and' in selector && Array.isArray(selector.$and)) {
return selector.$and.some(hasDeletedTrue);
}

if ('$nor' in selector && Array.isArray(selector.$nor)) {
return !selector.$nor.every((condition) => !hasDeletedTrue(condition));
}

return false;
}
23 changes: 20 additions & 3 deletions src/rx-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ import {
getQueryMatcher,
getSortComparator,
normalizeMangoQuery,
runQueryUpdateFunction
runQueryUpdateFunction,
selectorIncludesDeleted

} from './rx-query-helper.ts';
import { RxQuerySingleResult } from './rx-query-single-result.ts';
Expand Down Expand Up @@ -199,6 +200,10 @@ export class RxQueryBase<
) as any;
}

get includesDeleted(): boolean {
return selectorIncludesDeleted(this.mangoQuery.selector);
}

// stores the changeEvent-number of the last handled change-event
public _latestChangeEvent: -1 | number = -1;

Expand Down Expand Up @@ -418,7 +423,14 @@ export class RxQueryBase<
)
};

(hookInput.mangoQuery.selector as any)._deleted = { $eq: false };
// Set _deleted to false if not explicitly set in selector
if (!this.includesDeleted) {
hookInput.mangoQuery.selector = {
...hookInput.mangoQuery.selector,
_deleted: { $eq: false },
};
}

if (hookInput.mangoQuery.index) {
hookInput.mangoQuery.index.unshift('_deleted');
}
Expand Down Expand Up @@ -816,7 +828,12 @@ async function __ensureEqual<RxDocType>(rxQuery: RxQueryBase<RxDocType, any>): P
}
}

if (rxQuery.op === 'count') {
if (rxQuery.includesDeleted) {
return rxQuery._execOverDatabase().then((newResultData) => {
rxQuery._setResultData(newResultData);
return true;
});
} else if (rxQuery.op === 'count') {
// 'count' query
const previousCount = ensureNotFalsy(rxQuery._result).count;
let newCount = previousCount;
Expand Down

0 comments on commit 7ff705b

Please sign in to comment.