Add Feature: SQL query generator
This commit is contained in:
parent
df967a4ffb
commit
f53a9bf00e
8
functions/sql/sql-generator.d.ts
vendored
Normal file
8
functions/sql/sql-generator.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export = sqlGenerator;
|
||||||
|
declare function sqlGenerator(Param0: {
|
||||||
|
genObject?: import("../../package-shared/types").ServerQueryParam;
|
||||||
|
tableName: string;
|
||||||
|
}): {
|
||||||
|
string: string;
|
||||||
|
values: string[];
|
||||||
|
} | undefined;
|
164
functions/sql/sql-generator.js
Normal file
164
functions/sql/sql-generator.js
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # SQL Query Generator
|
||||||
|
* @description Generates an SQL Query for node module `mysql` or `serverless-mysql`
|
||||||
|
* @type {import("../../package-shared/types").SqlGeneratorFn}
|
||||||
|
*/
|
||||||
|
function sqlGenerator({ tableName, genObject }) {
|
||||||
|
if (!genObject) return undefined;
|
||||||
|
|
||||||
|
const finalQuery = genObject.query ? genObject.query : undefined;
|
||||||
|
|
||||||
|
const queryKeys = finalQuery ? Object.keys(finalQuery) : undefined;
|
||||||
|
|
||||||
|
/** @type {string[]} */
|
||||||
|
const sqlSearhValues = [];
|
||||||
|
const sqlSearhString = queryKeys?.map((field) => {
|
||||||
|
const queryObj = finalQuery?.[field];
|
||||||
|
if (!queryObj) return;
|
||||||
|
|
||||||
|
let str = `${field}=?`;
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof queryObj.value == "string" ||
|
||||||
|
typeof queryObj.value == "number"
|
||||||
|
) {
|
||||||
|
const valueParsed = String(queryObj.value);
|
||||||
|
if (queryObj.equality == "LIKE") {
|
||||||
|
str = `LOWER(${field}) LIKE LOWER('%${valueParsed}%')`;
|
||||||
|
} else {
|
||||||
|
sqlSearhValues.push(valueParsed);
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(queryObj.value)) {
|
||||||
|
/** @type {string[]} */
|
||||||
|
const strArray = [];
|
||||||
|
queryObj.value.forEach((val) => {
|
||||||
|
const valueParsed = val;
|
||||||
|
if (queryObj.equality == "LIKE") {
|
||||||
|
strArray.push(
|
||||||
|
`LOWER(${field}) LIKE LOWER('%${valueParsed}%')`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
strArray.push(`${field} = ?`);
|
||||||
|
sqlSearhValues.push(valueParsed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
str = "(" + strArray.join(` ${queryObj.operator || "AND"} `) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
});
|
||||||
|
|
||||||
|
function generateJoinStr(
|
||||||
|
/** @type {import("../../package-shared/types").ServerQueryParamsJoinMatchObject} */ mtch,
|
||||||
|
/** @type {import("../../package-shared/types").ServerQueryParamsJoin} */ join
|
||||||
|
) {
|
||||||
|
return `${
|
||||||
|
typeof mtch.source == "object" ? mtch.source.tableName : tableName
|
||||||
|
}.${
|
||||||
|
typeof mtch.source == "object" ? mtch.source.fieldName : mtch.source
|
||||||
|
}=${
|
||||||
|
typeof mtch.target == "object"
|
||||||
|
? mtch.target.tableName
|
||||||
|
: join.tableName
|
||||||
|
}.${
|
||||||
|
typeof mtch.target == "object" ? mtch.target.fieldName : mtch.target
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let queryString = (() => {
|
||||||
|
let str = "SELECT";
|
||||||
|
if (genObject.selectFields?.[0]) {
|
||||||
|
if (genObject.join) {
|
||||||
|
str += ` ${genObject.selectFields
|
||||||
|
?.map((fld) => `${tableName}.${fld}`)
|
||||||
|
.join(",")}`;
|
||||||
|
} else {
|
||||||
|
str += ` ${genObject.selectFields?.join(",")}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (genObject.join) {
|
||||||
|
str += ` ${tableName}.*`;
|
||||||
|
} else {
|
||||||
|
str += " *";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genObject.join) {
|
||||||
|
str +=
|
||||||
|
"," +
|
||||||
|
genObject.join
|
||||||
|
.map((joinObj) => {
|
||||||
|
if (joinObj.selectFields) {
|
||||||
|
return joinObj.selectFields
|
||||||
|
.map((slFld) => {
|
||||||
|
if (typeof slFld == "string") {
|
||||||
|
return `${joinObj.tableName}.${slFld}`;
|
||||||
|
} else if (typeof slFld == "object") {
|
||||||
|
let aliasSlctFld = `${joinObj.tableName}.${slFld.field}`;
|
||||||
|
if (slFld.alias)
|
||||||
|
aliasSlctFld += ` as ${slFld.alias}`;
|
||||||
|
return aliasSlctFld;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join(",");
|
||||||
|
} else {
|
||||||
|
return `${joinObj.tableName}.*`;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
str += ` FROM ${tableName}`;
|
||||||
|
|
||||||
|
if (genObject.join) {
|
||||||
|
str +=
|
||||||
|
" " +
|
||||||
|
genObject.join
|
||||||
|
.map((join) => {
|
||||||
|
return (
|
||||||
|
join.joinType +
|
||||||
|
" " +
|
||||||
|
join.tableName +
|
||||||
|
" ON " +
|
||||||
|
(() => {
|
||||||
|
if (Array.isArray(join.match)) {
|
||||||
|
return (
|
||||||
|
"(" +
|
||||||
|
join.match
|
||||||
|
.map((mtch) =>
|
||||||
|
generateJoinStr(mtch, join)
|
||||||
|
)
|
||||||
|
.join(" AND ") +
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
} else if (typeof join.match == "object") {
|
||||||
|
return generateJoinStr(join.match, join);
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (sqlSearhString) {
|
||||||
|
const stringOperator = genObject?.searchOperator || "AND";
|
||||||
|
queryString += ` WHERE ${sqlSearhString.join(` ${stringOperator} `)} `;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genObject.order)
|
||||||
|
queryString += ` ORDER BY ${genObject.order.field} ${genObject.order.strategy}`;
|
||||||
|
if (genObject.limit) queryString += ` LIMIT ${genObject.limit}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
string: queryString,
|
||||||
|
values: sqlSearhValues,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = sqlGenerator;
|
4
index.d.ts
vendored
4
index.d.ts
vendored
@ -24,6 +24,9 @@ export namespace user {
|
|||||||
import getSchema = require("./utils/get-schema");
|
import getSchema = require("./utils/get-schema");
|
||||||
import sanitizeSql = require("./utils/functions/sanitizeSql");
|
import sanitizeSql = require("./utils/functions/sanitizeSql");
|
||||||
import datasquirelClient = require("./client");
|
import datasquirelClient = require("./client");
|
||||||
|
export namespace sql {
|
||||||
|
export { sqlGenerator };
|
||||||
|
}
|
||||||
import uploadImage = require("./utils/upload-image");
|
import uploadImage = require("./utils/upload-image");
|
||||||
import uploadFile = require("./utils/upload-file");
|
import uploadFile = require("./utils/upload-file");
|
||||||
import deleteFile = require("./utils/delete-file");
|
import deleteFile = require("./utils/delete-file");
|
||||||
@ -39,4 +42,5 @@ import getToken = require("./users/get-token");
|
|||||||
import validateToken = require("./users/validate-token");
|
import validateToken = require("./users/validate-token");
|
||||||
import loginWithGoogle = require("./users/social/google-auth");
|
import loginWithGoogle = require("./users/social/google-auth");
|
||||||
import loginWithGithub = require("./users/social/github-auth");
|
import loginWithGithub = require("./users/social/github-auth");
|
||||||
|
import sqlGenerator = require("./functions/sql/sql-generator");
|
||||||
export { get, post, getSchema, sanitizeSql, datasquirelClient as client };
|
export { get, post, getSchema, sanitizeSql, datasquirelClient as client };
|
||||||
|
21
index.js
21
index.js
@ -28,6 +28,7 @@ const validateToken = require("./users/validate-token");
|
|||||||
|
|
||||||
const sanitizeSql = require("./utils/functions/sanitizeSql");
|
const sanitizeSql = require("./utils/functions/sanitizeSql");
|
||||||
const datasquirelClient = require("./client");
|
const datasquirelClient = require("./client");
|
||||||
|
const sqlGenerator = require("./functions/sql/sql-generator");
|
||||||
|
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
@ -62,17 +63,25 @@ const media = {
|
|||||||
deleteFile: deleteFile,
|
deleteFile: deleteFile,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQL Utils
|
||||||
|
*/
|
||||||
|
const sql = {
|
||||||
|
sqlGenerator,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main Export
|
* Main Export
|
||||||
*/
|
*/
|
||||||
const datasquirel = {
|
const datasquirel = {
|
||||||
get: get,
|
get,
|
||||||
post: post,
|
post,
|
||||||
media: media,
|
media,
|
||||||
user: user,
|
user,
|
||||||
getSchema: getSchema,
|
getSchema,
|
||||||
sanitizeSql: sanitizeSql,
|
sanitizeSql,
|
||||||
client: datasquirelClient,
|
client: datasquirelClient,
|
||||||
|
sql,
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = datasquirel;
|
module.exports = datasquirel;
|
||||||
|
74
package-shared/types/index.d.ts
vendored
74
package-shared/types/index.d.ts
vendored
@ -1134,3 +1134,77 @@ export type FetchApiReturn = {
|
|||||||
msg?: string;
|
msg?: string;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ServerQueryParam = {
|
||||||
|
selectFields?: string[];
|
||||||
|
query?: ServerQueryQueryObject;
|
||||||
|
limit?: number;
|
||||||
|
order?: {
|
||||||
|
field: string;
|
||||||
|
strategy: "ASC" | "DESC";
|
||||||
|
};
|
||||||
|
searchOperator?: "AND" | "OR";
|
||||||
|
searchEquality?: "EQUAL" | "LIKE";
|
||||||
|
addUserId?: {
|
||||||
|
fieldName: string;
|
||||||
|
};
|
||||||
|
join?: ServerQueryParamsJoin[];
|
||||||
|
} & {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ServerQueryQueryObject = {
|
||||||
|
[key: string]: {
|
||||||
|
value: string | string[];
|
||||||
|
operator?: "AND" | "OR";
|
||||||
|
equality?: "EQUAL" | "LIKE";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FetchDataParams = {
|
||||||
|
path: string;
|
||||||
|
method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
|
||||||
|
body?: object | string;
|
||||||
|
query?: AuthFetchQuery;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AuthFetchQuery = ServerQueryParam & {
|
||||||
|
[key: string]: string | number | { [key: string]: any };
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ServerQueryParamsJoin = {
|
||||||
|
joinType: "INNER JOIN" | "JOIN" | "LEFT JOIN" | "RIGHT JOIN";
|
||||||
|
tableName: string;
|
||||||
|
match?:
|
||||||
|
| ServerQueryParamsJoinMatchObject
|
||||||
|
| ServerQueryParamsJoinMatchObject[];
|
||||||
|
selectFields?: (
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
field: string;
|
||||||
|
alias?: string;
|
||||||
|
}
|
||||||
|
)[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ServerQueryParamsJoinMatchObject = {
|
||||||
|
/** Field name from the **Root Table** */
|
||||||
|
source: string | ServerQueryParamsJoinMatchSourceTargetObject;
|
||||||
|
/** Field name from the **Join Table** */
|
||||||
|
target: string | ServerQueryParamsJoinMatchSourceTargetObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ServerQueryParamsJoinMatchSourceTargetObject = {
|
||||||
|
tableName: string;
|
||||||
|
fieldName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SqlGeneratorFn = (Param0: {
|
||||||
|
genObject?: ServerQueryParam;
|
||||||
|
tableName: string;
|
||||||
|
}) =>
|
||||||
|
| {
|
||||||
|
string: string;
|
||||||
|
values: string[];
|
||||||
|
}
|
||||||
|
| undefined;
|
||||||
|
Loading…
Reference in New Issue
Block a user