I've devised a TypeScript method that employs method chaining to craft a simple SQL query builder. It includes the essential query methods. I want to restrict users from calling the offset method, for instance, if they haven't previously called limit or have called where twice. While I know I can utilize a map to track the previously invoked methods, I'm curious if there's a more streamlined solution to this dilemma. Below is my current query builder method:
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 an elegant way to control the flow of method chaining?