Skip to content

Commit

Permalink
feat: add sort expression feature
Browse files Browse the repository at this point in the history
  • Loading branch information
kostyazgara committed Feb 27, 2024
1 parent 2646b4f commit 2523ca3
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
ComparisonOperator,
CursorPaginationOptions,
} from '../interfaces';
import { buildSortPath, getSortDirection } from '@knexion/sort';
import { extractModifiers, getSortDirection } from '@knexion/sort';

export class CursorPaginationInterceptor<
TRecord,
Expand Down Expand Up @@ -154,23 +154,26 @@ export class CursorPaginationInterceptor<
alias: string,
next?: boolean,
): void {
const [dir, column] = getSortDirection(currentSortProperty);
const [placeholder, bindings] = buildSortPath(column, alias);
const [dir, sortExpression] = getSortDirection(currentSortProperty);
const { column, where, whereBindings } = extractModifiers(
sortExpression,
alias,
);
const lastSortValue = pageInfo[column];
const isNullLastSortValue = lastSortValue === null;
if (isNullLastSortValue) {
builder.whereRaw(`${placeholder} is null`, bindings);
builder.whereRaw(`${where} is null`, whereBindings);
} else {
builder.where(
rawBuilder(placeholder, bindings),
rawBuilder(where, whereBindings),
this.getWhereSortOperator(dir, next),
lastSortValue,
);
}
builder.andWhere((andWereBuilder) => {
if (!isNullLastSortValue) {
andWereBuilder.where(
rawBuilder(placeholder, bindings),
rawBuilder(where, whereBindings),
this.getAndWhereSortOperator(dir, next),
lastSortValue,
);
Expand Down
9 changes: 6 additions & 3 deletions packages/sort/lib/interceptors/sort.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
KnexionInterceptor,
SelectDatabaseOptions,
} from '@knexion/core';
import { buildSortPath, getSortDirection } from '../utils';
import { extractModifiers, getSortDirection } from '../utils';
import { SortOptions } from '../interfaces';

export class SortInterceptor<TRecord, TResult>
Expand All @@ -26,12 +26,15 @@ export class SortInterceptor<TRecord, TResult>
if (sort && Array.isArray(sort)) {
sort.forEach((property) => {
const [direction, path] = getSortDirection(property);
const [placeholder, bindings] = buildSortPath(path, options.alias);
const { placeholder, placeholderBindings } = extractModifiers(
path,
options.alias,
);
queryBuilder.orderByRaw(
`${placeholder} ${direction} nulls ${
direction === 'desc' ? 'last' : 'first'
}`,
bindings,
placeholderBindings,
);
});
}
Expand Down
28 changes: 0 additions & 28 deletions packages/sort/lib/utils/build-sort-path.ts

This file was deleted.

92 changes: 92 additions & 0 deletions packages/sort/lib/utils/extract-modifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { addPrefixColumn } from '@knexion/core';

interface SortModifiers {
column: string;
placeholder: string;
placeholderBindings: string[];
where: string;
whereBindings: string[];
}

const buildJsonPlaceholder = (
column: string,
jsonPath: string[],
): [string, string[]] => {
const [lastProperty] = jsonPath.splice(-1);
if (!jsonPath.length) {
return [`??->>?`, [column, lastProperty]];
}
return [
`??->${jsonPath.map(() => '??').join('->')}->>?`,
[column, ...jsonPath, lastProperty],
];
};

const getPlaceholder = (path: string, alias?: string): [string, string[]] => {
const [column, ...jsonPath] = path.split('->');
const isJsonPlaceholder = !!jsonPath.length;

if (column.startsWith('skipAlias:')) {
const columnName = column.slice(10);
return isJsonPlaceholder
? buildJsonPlaceholder(columnName, jsonPath)
: ['??', [columnName]];
}

const aliasedColumn =
column.split('.').length > 1 ? column : addPrefixColumn(column, alias);
return isJsonPlaceholder
? buildJsonPlaceholder(aliasedColumn, jsonPath)
: ['??', [aliasedColumn]];
};

const lookupModifiers = (
definitions: string[],
alias?: string,
): SortModifiers => {
const [placeholder, placeholderBindings] = getPlaceholder(
definitions[0],
alias,
);

const where =
definitions
.find((definition) => definition.startsWith('where:'))
?.slice(6) ?? placeholder;
const whereBindings =
definitions
.find((definition) => definition.startsWith('whereBindings:'))
?.slice(14)
.split(',') ?? [];

return {
column: placeholderBindings[0],
placeholder,
placeholderBindings,
where,
whereBindings,
};
};

export const extractModifiers = (
path: string,
alias?: string,
): SortModifiers => {
const definitions = path.split(';');

if (definitions.length > 1) {
return lookupModifiers(definitions, alias);
}

const [placeholder, placeholderBindings] = getPlaceholder(
definitions[0],
alias,
);
return {
column: placeholderBindings[0],
placeholder,
placeholderBindings,
where: placeholder,
whereBindings: placeholderBindings,
};
};
2 changes: 1 addition & 1 deletion packages/sort/lib/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './build-sort-path';
export * from './extract-modifiers';
export * from './get-sort-direction';

0 comments on commit 2523ca3

Please sign in to comment.