Fixed NQL filter column mapping for BookskhelfRepository
no issue When filtering and using the BookshelfRepository, you had to use the column names instead of the entitiy field names. This is fixed by adding a transformer. Long term we want to move the NQL parsing away from the repository and into the API layer, and pass along the Mongo filter probably.
This commit is contained in:
parent
b1cd7dd898
commit
383069a1e5
@ -25,6 +25,7 @@
|
||||
"sinon": "15.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tryghost/nql": "0.11.0"
|
||||
"@tryghost/mongo-utils": "0.5.0",
|
||||
"knex": "2.4.2"
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import {Knex} from 'knex';
|
||||
import {mapKeys, chainTransformers} from '@tryghost/mongo-utils';
|
||||
|
||||
type Entity<T> = {
|
||||
id: T;
|
||||
deleted: boolean;
|
||||
deleted: boolean
|
||||
}
|
||||
|
||||
type Order<T> = {
|
||||
@ -14,7 +15,7 @@ export type ModelClass<T> = {
|
||||
destroy: (data: {id: T}) => Promise<void>;
|
||||
findOne: (data: {id: T}, options?: {require?: boolean}) => Promise<ModelInstance<T> | null>;
|
||||
add: (data: object) => Promise<ModelInstance<T>>;
|
||||
getFilteredCollection: (options: {filter?: string}) => {
|
||||
getFilteredCollection: (options: {filter?: string, mongoTransformer?: unknown}) => {
|
||||
count(): Promise<number>,
|
||||
query: (f: (q: Knex.QueryBuilder) => void) => void,
|
||||
fetchAll: () => Promise<ModelInstance<T>[]>
|
||||
@ -39,14 +40,26 @@ export abstract class BookshelfRepository<IDType, T extends Entity<IDType>> {
|
||||
}
|
||||
|
||||
protected abstract toPrimitive(entity: T): object;
|
||||
protected abstract entityFieldToColumn(field: keyof T): string;
|
||||
protected abstract modelToEntity(model: ModelInstance<IDType>): Promise<T|null> | T | null;
|
||||
protected abstract modelToEntity (model: ModelInstance<IDType>): Promise<T|null> | T | null
|
||||
protected abstract getFieldToColumnMap(): Record<keyof T, string>;
|
||||
|
||||
#entityFieldToColumn(field: keyof T): string {
|
||||
const mapping = this.getFieldToColumnMap();
|
||||
return mapping[field];
|
||||
}
|
||||
|
||||
#orderToString(order?: OrderOption<T>) {
|
||||
if (!order || order.length === 0) {
|
||||
return;
|
||||
}
|
||||
return order.map(({field, direction}) => `${this.entityFieldToColumn(field)} ${direction}`).join(',');
|
||||
return order.map(({field, direction}) => `${this.#entityFieldToColumn(field)} ${direction}`).join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* Map all the fields in an NQL filter to the names of the model
|
||||
*/
|
||||
#getNQLKeyTransformer() {
|
||||
return chainTransformers(...mapKeys(this.getFieldToColumnMap()));
|
||||
}
|
||||
|
||||
async save(entity: T): Promise<void> {
|
||||
@ -70,7 +83,10 @@ export abstract class BookshelfRepository<IDType, T extends Entity<IDType>> {
|
||||
}
|
||||
|
||||
async #fetchAll({filter, order, page, limit}: { filter?: string; order?: OrderOption<T>; page?: number; limit?: number }): Promise<T[]> {
|
||||
const collection = this.Model.getFilteredCollection({filter});
|
||||
const collection = this.Model.getFilteredCollection({
|
||||
filter,
|
||||
mongoTransformer: this.#getNQLKeyTransformer()
|
||||
});
|
||||
const orderString = this.#orderToString(order);
|
||||
|
||||
if ((limit && page) || orderString) {
|
||||
@ -110,7 +126,10 @@ export abstract class BookshelfRepository<IDType, T extends Entity<IDType>> {
|
||||
}
|
||||
|
||||
async getCount({filter}: { filter?: string } = {}): Promise<number> {
|
||||
const collection = this.Model.getFilteredCollection({filter});
|
||||
const collection = this.Model.getFilteredCollection({
|
||||
filter,
|
||||
mongoTransformer: this.#getNQLKeyTransformer()
|
||||
});
|
||||
return await collection.count();
|
||||
}
|
||||
}
|
||||
|
1
ghost/bookshelf-repository/src/libraries.d.ts
vendored
Normal file
1
ghost/bookshelf-repository/src/libraries.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module '@tryghost/mongo-utils';
|
Loading…
Reference in New Issue
Block a user