mobxjs / mst-gql

Bindings for mobx-state-tree and GraphQL

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Complex filters handling using generated code

DanielAndrysek opened this issue · comments

Hi

I've found the issue with query generating by generated code. We are using Symfony 6 + Api Platform 2.6 for backend and angular with mst-gql for frontend. We're using soft delete functionality so in order to filter out results from query we have implemented "Exists" filter.

Generated selector:

export class ProductSupplierModelSelector extends QueryBuilder {
  get id() { return this.__attr(`id`) }
  get name() { return this.__attr(`name`) }
  get deletedAt() { return this.__attr(`deletedAt`) }
  get created() { return this.__attr(`created`) }
  get modified() { return this.__attr(`modified`) }
  get deleted() { return this.__attr(`deleted`) }
  products(builder: string | ProductModelSelector | ((selector: ProductModelSelector) => ProductModelSelector) | undefined, args?: { name?: (string | null), supplier?: (string | null), supplierList?: (string | null)[], family?: (string | null), familyList?: (string | null)[], exists?: (ProductFilterExists | null)[] }) { return this.__child(`products`+ (args ? '('+['name', 'supplier', 'supplierList', 'family', 'familyList', 'exists'].map((argName) => ((args as any)[argName] ? `${argName}: ${JSON.stringify((args as any)[argName])}` : null) ).filter((v) => v!=null).join(', ') + ')': ''), ProductModelSelector, builder) }
}

The generated code produces query like:

products(exists: [{"deletedAt":false}])

Instead of:

products(exists: [{deletedAt:false}])

The reason of this is the part with JSON.stringify:

${JSON.stringify((args as any)[argName])}`

My solution is to substitute it with a method wich converts complex objects into queryable string without escaping object keys:

const filterToString = (filter: any): string => {
    if (Array.isArray(filter)){
        return `[${filter.map((tmp) => filterToString(tmp)).join(", ")}]`;
    }else if (typeof filter === "object"){
        const objectKeys = Object.keys(filter);
        return `{${objectKeys.map((key) => `${key}:${filterToString(filter[key])}`).join(", ")}}`;
    }
    return JSON.stringify(filter);
};

Is there any other way to avoid this issue?