Skip to content

Commit

Permalink
Merge pull request kurierjs#7 from Martinarbez/main
Browse files Browse the repository at this point in the history
Filters for included manyToMany relationships
  • Loading branch information
Martinarbez authored May 9, 2024
2 parents 91661f5 + 3f6d164 commit c496175
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 3 deletions.
33 changes: 30 additions & 3 deletions src/processors/knex-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import pick from "../utils/pick";
import promiseHashMap from "../utils/promise-hash-map";
import OperationProcessor from "./operation-processor";
import { KnexOperators as operators } from "../utils/operators";
import { pluralize } from "../utils/string";
import { underscore, pluralize } from "../utils/string";

const getWhereMethod = (value: string, operator: string) => {
if (value !== "null") {
Expand Down Expand Up @@ -155,10 +155,37 @@ export default class KnexProcessor<ResourceT extends Resource> extends Operation
const primaryKey = this.resourceClass.schema.primaryKeyName || DEFAULT_PRIMARY_KEY;
const filters = params ? { [primaryKey]: id, ...(params.filter || {}) } : { [primaryKey]: id };

const records: KnexRecord[] = await this.getQuery()
let query = this.getQuery();

let columns = this.getColumns(this.appInstance.app.serializer, (params || {}).fields);

if(params?.include){
let isIncluded = false;
for (const include of params.include) {
if(include.includes('.')){
continue;
}
const relationship = this.resourceClass.schema.relationships[include];
if (relationship.manyToMany && relationship.foreignKeyName&& relationship.intermediateTable && filters.hasOwnProperty(relationship.foreignKeyName)) {
if(!isIncluded){
columns = columns.map(column => {
if(typeof column !== 'string' && columns.toString().includes('count')){
return column
}
return `${this.tableName}.${column}`})
isIncluded = true
}
const intermediateTableColumn = `${underscore(op.ref.type)}_id`
query.innerJoin(relationship.intermediateTable, `${this.tableName}.${primaryKey}`, `${relationship.intermediateTable}.${intermediateTableColumn}`)
columns.push(`${relationship.intermediateTable}.${relationship.foreignKeyName} as ${relationship.foreignKeyName}`)
}
}
}

const records: KnexRecord[] = await query
.where((queryBuilder) => this.filtersToKnex(queryBuilder, filters))
.modify((queryBuilder) => this.optionsBuilder(queryBuilder, params || {}))
.select(this.getColumns(this.appInstance.app.serializer, (params || {}).fields));
.select(columns);

if (!records.length && id) {
throw JsonApiErrors.RecordNotExists();
Expand Down
12 changes: 12 additions & 0 deletions tests/test-suite/acceptance/article.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ describe.each(transportLayers)("Transport Layer: %s", (transportLayer) => {
expect(result.body).toEqual({ data: [articles.toGet.response[0]] });
});

it("Search Articles with included tags, filter by tagId", async () => {
const articleCreationResult = await request.post(`/articles`).send(articles.forCreation.requests.jsonapi);
expect(articleCreationResult.status).toEqual(201);
const firstArticleFilteredByFirstTag = await request.get(`/articles?include=tags&filter[tag_id]=1`);
expect(firstArticleFilteredByFirstTag.status).toEqual(200);
expect(firstArticleFilteredByFirstTag.body.data.length).toEqual(2);
const firstArticleFilteredBySecondTag = await request.get(`/articles?include=tags&filter[tag_id]=2`);
expect(firstArticleFilteredBySecondTag.status).toEqual(200);
expect(firstArticleFilteredBySecondTag.body.data.length).toEqual(1);
expect(firstArticleFilteredBySecondTag.body.data[0].relationships.tags.data).toEqual(articles.forUpdate.requests.jsonapi.data.relationships.tags.data);
});

it("Authenticated - Get an specific article with it's votes and author - Multiple types include", async () => {
const authData = await getAuthenticationData();
const result = await request.get("/articles/1?include=author,votes").set("Authorization", authData.token);
Expand Down
113 changes: 113 additions & 0 deletions tests/test-suite/acceptance/factories/article.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,119 @@ export default {
},
],
},
multipleArticlesIncludedTags: {
data: [
{
id: 1,
type: "article",
attributes: {
body: "this is test 1",
voteCount: 2,
},
relationships: {
votes: {
data: [
{
id: 1,
type: "vote",
},
{
id: 2,
type: "vote",
},
],
},
author: {
data: {
id: 1,
type: "user",
},
},
},
meta: {
hello: "world",
},
},

],
included: [
{
id: 1,
type: "vote",
attributes: {
points: 10,
createdOn: null,
updatedOn: null,
updatedBy: null,
createdBy: null,
},
relationships: {
user: {
data: {
id: 1,
type: "user",
},
},
article: {
data: {
id: 1,
type: "article",
},
},
},
},
{
id: 2,
type: "vote",
attributes: {
points: 2,
createdOn: null,
updatedOn: null,
updatedBy: null,
createdBy: null,
},
relationships: {
user: {
data: {
id: 1,
type: "user",
},
},
article: {
data: {
id: 1,
type: "article",
},
},
},
},
{
id: 3,
type: "vote",
attributes: {
points: 8,
createdOn: null,
updatedOn: null,
updatedBy: null,
createdBy: null,
},
relationships: {
user: {
data: {
id: 3,
type: "user",
},
},
article: {
data: {
id: 3,
type: "article",
},
},
},
},
],
},
multipleArticlesIncludedVotes: {
data: [
{
Expand Down

0 comments on commit c496175

Please sign in to comment.