'JS Method Chaining Controlling Flow
I have created a method in Typescript which utilizes method chaining to create a simple sql query builder. It implements the basic query methods. What I would like to do is not allow someone to call the offset method for example if they havent called limit previously or calling where twice. I know I can implement something via a map which stores the previously called methods but I was wondering if there is a clean solution to this problem. My current query builder method is
public qb = () =>
{
let query = this.SELECT;
const api = {
where: (key: string, value: number|string) =>
{
query = sql`${query} WHERE ${sql.identifier([key])} = ${value}`;
return api;
},
and: (key: string, value: number|string) =>
{
query = sql`${query} AND ${sql.identifier([key])} = ${value}`;
return api;
},
orderBy: (key: string, order: 'ASC'|'DESC') =>
{
query = sql`${query} ORDER BY ${sql.identifier([key])} ${order}`;
return api;
},
limit: (limit: number) =>
{
query = sql`${query} LIMIT ${limit}`;
return api;
},
offset: (offset: number) =>
{
query = sql`${query} OFFSET ${offset}`;
return api;
},
get: async () => this.rowMapper(await this.database.query(query)),
};
return api;
};
Is there a nice way to force the flow of the method chaining?
Solution 1:[1]
The solution I ended up going with is creating multiple objects which have different methods inside of them. The solution is not the cleanest but I could not find a better one
public qb = () =>
{
let query = this.SELECT;
const get = async () => this.rowMapper(await this.database.query(query));
const limit = (_limit: number) =>
{
query = sql`${query} LIMIT ${_limit}`;
return {
offset: (offset: number) =>
{
query = sql`${query} OFFSET ${offset}`;
return { get };
},
get,
};
};
const api2 = {
and: (key: string, value: number|string) =>
{
query = sql`${query} AND ${sql.identifier([key])} = ${value}`;
return api2;
},
orderBy: (key: string, order: 'ASC'|'DESC') =>
{
query = sql`${query} ORDER BY ${sql.identifier([key])} ${order}`;
return {
limit,
get,
};
},
limit,
get,
};
const api = {
where: (key: string, value: number|string) =>
{
query = sql`${query} WHERE ${sql.identifier([key])} = ${value}`;
return api2;
},
};
return api;
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
