agent-sql 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +6 -2
- package/dist/index.mjs +50 -29
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -15,10 +15,10 @@ type WhereGuard = GuardCol & {
|
|
|
15
15
|
};
|
|
16
16
|
type OneOrTwoDots<S extends string> = S extends `${infer A}.${infer B}.${infer C}` ? A extends `${string}.${string}` ? never : B extends `${string}.${string}` ? never : C extends `${string}.${string}` ? never : S : S extends `${infer A}.${infer B}` ? A extends `${string}.${string}` ? never : B extends `${string}.${string}` ? never : S : never;
|
|
17
17
|
type SchemaGuardKeys<T> = { [Table in keyof T & string]: `${Table}.${keyof T[Table] & string}` }[keyof T & string];
|
|
18
|
-
declare function applyGuards(ast: SelectStatement, guards: WhereGuard[], limit
|
|
18
|
+
declare function applyGuards(ast: SelectStatement, guards: WhereGuard[], limit: number): Result<SelectStatement>;
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region src/output.d.ts
|
|
21
|
-
declare function outputSql(ast: SelectStatement): string;
|
|
21
|
+
declare function outputSql(ast: SelectStatement, pretty?: boolean): string;
|
|
22
22
|
//#endregion
|
|
23
23
|
//#region src/parse.d.ts
|
|
24
24
|
declare function parseSql(expr: string): Result<SelectStatement>;
|
|
@@ -27,22 +27,26 @@ declare function parseSql(expr: string): Result<SelectStatement>;
|
|
|
27
27
|
declare function agentSql<S extends string>(sql: string, column: S & OneOrTwoDots<S>, value: GuardVal, {
|
|
28
28
|
schema,
|
|
29
29
|
limit,
|
|
30
|
+
pretty,
|
|
30
31
|
db,
|
|
31
32
|
allowExtraFunctions
|
|
32
33
|
}?: {
|
|
33
34
|
schema?: Schema;
|
|
34
35
|
limit?: number;
|
|
36
|
+
pretty?: boolean;
|
|
35
37
|
db?: DbType;
|
|
36
38
|
allowExtraFunctions?: string[];
|
|
37
39
|
}): string;
|
|
38
40
|
declare function createAgentSql<T extends Schema, S extends SchemaGuardKeys<T>>(schema: T, guards: Record<S, GuardVal>, opts: {
|
|
39
41
|
limit?: number;
|
|
42
|
+
pretty?: boolean;
|
|
40
43
|
throws: false;
|
|
41
44
|
db?: DbType;
|
|
42
45
|
allowExtraFunctions?: string[];
|
|
43
46
|
}): (expr: string) => Result<string>;
|
|
44
47
|
declare function createAgentSql<T extends Schema, S extends SchemaGuardKeys<T>>(schema: T, guards: Record<S, GuardVal>, opts?: {
|
|
45
48
|
limit?: number;
|
|
49
|
+
pretty?: boolean;
|
|
46
50
|
throws?: true;
|
|
47
51
|
db?: DbType;
|
|
48
52
|
allowExtraFunctions?: string[];
|
package/dist/index.mjs
CHANGED
|
@@ -36,6 +36,7 @@ function returnOrThrow(result, throws) {
|
|
|
36
36
|
}
|
|
37
37
|
//#endregion
|
|
38
38
|
//#region src/functions.ts
|
|
39
|
+
const DEFAULT_DB = "postgres";
|
|
39
40
|
const COMMON_FUNCTIONS = [
|
|
40
41
|
"count",
|
|
41
42
|
"sum",
|
|
@@ -779,22 +780,24 @@ function unreachable(x) {
|
|
|
779
780
|
}
|
|
780
781
|
//#endregion
|
|
781
782
|
//#region src/output.ts
|
|
782
|
-
function outputSql(ast) {
|
|
783
|
-
|
|
783
|
+
function outputSql(ast, pretty = false) {
|
|
784
|
+
const res = r(ast, pretty);
|
|
785
|
+
if (pretty) return res;
|
|
786
|
+
return normaliseWhitespace(res);
|
|
784
787
|
}
|
|
785
788
|
function normaliseWhitespace(s) {
|
|
786
789
|
return s.replace(/\s+/g, " ").trim();
|
|
787
790
|
}
|
|
788
|
-
function r(node) {
|
|
791
|
+
function r(node, pretty = false) {
|
|
789
792
|
if (node === null || node === void 0) return "";
|
|
790
793
|
if (typeof node === "string") return node;
|
|
791
794
|
if (typeof node === "number") return String(node);
|
|
792
795
|
switch (node.type) {
|
|
793
|
-
case "select": return handleSelect(node);
|
|
796
|
+
case "select": return handleSelect(node, pretty);
|
|
794
797
|
case "select_from": return handleSelectFrom(node);
|
|
795
|
-
case "join": return handleJoin(node);
|
|
798
|
+
case "join": return handleJoin(node, pretty);
|
|
796
799
|
case "join_on":
|
|
797
|
-
case "join_using": return handleJoinCondition(node);
|
|
800
|
+
case "join_using": return handleJoinCondition(node, pretty);
|
|
798
801
|
case "table_ref": return handleTableRef(node);
|
|
799
802
|
case "limit": return handleLimit(node);
|
|
800
803
|
case "offset": return handleOffset(node);
|
|
@@ -822,7 +825,7 @@ function r(node) {
|
|
|
822
825
|
case "case_expr": return handleCaseExpr(node);
|
|
823
826
|
case "cast_expr": return handleCastExpr(node);
|
|
824
827
|
case "where_value": return handleWhereValue(node);
|
|
825
|
-
case "column": return handleColumn(node);
|
|
828
|
+
case "column": return handleColumn(node, pretty);
|
|
826
829
|
case "column_expr": return handleColumnExpr(node);
|
|
827
830
|
case "column_ref": return handleColumnRef(node);
|
|
828
831
|
case "alias": return handleAlias(node);
|
|
@@ -830,23 +833,37 @@ function r(node) {
|
|
|
830
833
|
default: return unreachable(node);
|
|
831
834
|
}
|
|
832
835
|
}
|
|
833
|
-
function
|
|
834
|
-
return t.map((n) => r(n).
|
|
836
|
+
function rMap(t, pretty = false, sep = ", ") {
|
|
837
|
+
return t.map((n) => r(n, pretty).trimEnd()).join(sep);
|
|
835
838
|
}
|
|
836
|
-
function handleSelect(node) {
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
+
function handleSelect(node, pretty) {
|
|
840
|
+
const distinctStr = node.distinct ? `${r(node.distinct)} ` : "";
|
|
841
|
+
const colSep = pretty ? ",\n" : ", ";
|
|
842
|
+
const joinSep = pretty ? "\n" : " ";
|
|
843
|
+
const joiner = pretty ? "\n" : " ";
|
|
844
|
+
return [
|
|
845
|
+
"SELECT",
|
|
846
|
+
`${distinctStr}${rMap(node.columns, pretty, colSep)}`,
|
|
847
|
+
r(node.from),
|
|
848
|
+
rMap(node.joins, pretty, joinSep),
|
|
849
|
+
r(node.where),
|
|
850
|
+
r(node.groupBy),
|
|
851
|
+
r(node.having),
|
|
852
|
+
r(node.orderBy),
|
|
853
|
+
r(node.limit),
|
|
854
|
+
r(node.offset)
|
|
855
|
+
].join(joiner);
|
|
839
856
|
}
|
|
840
857
|
function handleDistinct(_node) {
|
|
841
858
|
return "DISTINCT";
|
|
842
859
|
}
|
|
843
860
|
function handleDistinctOn(node) {
|
|
844
|
-
return `DISTINCT ON (${
|
|
861
|
+
return `DISTINCT ON (${rMap(node.columns)})`;
|
|
845
862
|
}
|
|
846
863
|
function handleSelectFrom(node) {
|
|
847
864
|
return `FROM ${r(node.table)}`;
|
|
848
865
|
}
|
|
849
|
-
function handleJoin(node) {
|
|
866
|
+
function handleJoin(node, pretty) {
|
|
850
867
|
const typeStr = {
|
|
851
868
|
inner: "INNER JOIN",
|
|
852
869
|
inner_outer: "INNER OUTER JOIN",
|
|
@@ -859,12 +876,13 @@ function handleJoin(node) {
|
|
|
859
876
|
cross: "CROSS JOIN",
|
|
860
877
|
natural: "NATURAL JOIN"
|
|
861
878
|
};
|
|
862
|
-
const cond = node.condition ?
|
|
879
|
+
const cond = node.condition ? `${handleJoinCondition(node.condition, pretty)}` : "";
|
|
863
880
|
return `${typeStr[node.joinType]} ${r(node.table)}${cond}`;
|
|
864
881
|
}
|
|
865
|
-
function handleJoinCondition(node) {
|
|
866
|
-
|
|
867
|
-
return
|
|
882
|
+
function handleJoinCondition(node, pretty) {
|
|
883
|
+
const prefix = pretty ? "\n " : " ";
|
|
884
|
+
if (node.type === "join_on") return `${prefix}ON ${r(node.expr)}`;
|
|
885
|
+
return `${prefix}USING (${node.columns.join(", ")})`;
|
|
868
886
|
}
|
|
869
887
|
function handleLimit(node) {
|
|
870
888
|
return `LIMIT ${node.value}`;
|
|
@@ -873,13 +891,13 @@ function handleOffset(node) {
|
|
|
873
891
|
return `OFFSET ${node.value}`;
|
|
874
892
|
}
|
|
875
893
|
function handleGroupBy(node) {
|
|
876
|
-
return `GROUP BY ${
|
|
894
|
+
return `GROUP BY ${rMap(node.items)}`;
|
|
877
895
|
}
|
|
878
896
|
function handleHaving(node) {
|
|
879
897
|
return `HAVING ${r(node.expr)}`;
|
|
880
898
|
}
|
|
881
899
|
function handleOrderBy(node) {
|
|
882
|
-
return `ORDER BY ${
|
|
900
|
+
return `ORDER BY ${rMap(node.items)}`;
|
|
883
901
|
}
|
|
884
902
|
function handleOrderByItem(node) {
|
|
885
903
|
const dir = node.direction ? ` ${node.direction.toUpperCase()}` : "";
|
|
@@ -914,7 +932,7 @@ function handleWhereBetween(node) {
|
|
|
914
932
|
return `${r(node.expr)}${node.not ? " NOT" : ""} BETWEEN ${r(node.low)} AND ${r(node.high)}`;
|
|
915
933
|
}
|
|
916
934
|
function handleWhereIn(node) {
|
|
917
|
-
return `${r(node.expr)}${node.not ? " NOT" : ""} IN (${
|
|
935
|
+
return `${r(node.expr)}${node.not ? " NOT" : ""} IN (${rMap(node.list)})`;
|
|
918
936
|
}
|
|
919
937
|
function handleCaseExpr(node) {
|
|
920
938
|
return `CASE${node.subject ? ` ${r(node.subject)}` : ""} ${node.whens.map((w) => `WHEN ${r(w.condition)} THEN ${r(w.result)}`).join(" ")}${node.else ? ` ELSE ${r(node.else)}` : ""} END`;
|
|
@@ -959,8 +977,8 @@ function handleWhereValue(node) {
|
|
|
959
977
|
default: return unreachable(node);
|
|
960
978
|
}
|
|
961
979
|
}
|
|
962
|
-
function handleColumn(node) {
|
|
963
|
-
return `${r(node.expr)} ${r(node.alias)}`;
|
|
980
|
+
function handleColumn(node, pretty) {
|
|
981
|
+
return `${pretty ? " " : ""}${r(node.expr)} ${r(node.alias)}`;
|
|
964
982
|
}
|
|
965
983
|
function handleAlias(node) {
|
|
966
984
|
return `AS ${node.name}`;
|
|
@@ -972,7 +990,7 @@ function handleColumnRef(node) {
|
|
|
972
990
|
function handleFuncCall(node) {
|
|
973
991
|
const { name, args } = node;
|
|
974
992
|
if (args.kind === "wildcard") return `${name}(*)`;
|
|
975
|
-
return `${name}(${args.distinct ? "DISTINCT " : ""}${
|
|
993
|
+
return `${name}(${args.distinct ? "DISTINCT " : ""}${rMap(args.args)})`;
|
|
976
994
|
}
|
|
977
995
|
function handleColumnExpr(node) {
|
|
978
996
|
switch (node.kind) {
|
|
@@ -985,7 +1003,7 @@ function handleColumnExpr(node) {
|
|
|
985
1003
|
//#endregion
|
|
986
1004
|
//#region src/guard.ts
|
|
987
1005
|
const DEFAULT_LIMIT = 1e4;
|
|
988
|
-
function applyGuards(ast, guards, limit
|
|
1006
|
+
function applyGuards(ast, guards, limit) {
|
|
989
1007
|
const ast2 = addWhereGuard(ast, guards);
|
|
990
1008
|
if (!ast2.ok) return ast2;
|
|
991
1009
|
return addLimitGuard(ast2.data, limit);
|
|
@@ -7186,21 +7204,23 @@ function parseSql(expr) {
|
|
|
7186
7204
|
}
|
|
7187
7205
|
//#endregion
|
|
7188
7206
|
//#region src/index.ts
|
|
7189
|
-
function agentSql(sql, column, value, { schema, limit, db =
|
|
7207
|
+
function agentSql(sql, column, value, { schema, limit = DEFAULT_LIMIT, pretty = false, db = DEFAULT_DB, allowExtraFunctions = [] } = {}) {
|
|
7190
7208
|
return privateAgentSql(sql, {
|
|
7191
7209
|
guards: { [column]: value },
|
|
7192
7210
|
schema,
|
|
7193
7211
|
limit,
|
|
7212
|
+
pretty,
|
|
7194
7213
|
db,
|
|
7195
7214
|
allowExtraFunctions,
|
|
7196
7215
|
throws: true
|
|
7197
7216
|
});
|
|
7198
7217
|
}
|
|
7199
|
-
function createAgentSql(schema, guards, { limit,
|
|
7218
|
+
function createAgentSql(schema, guards, { limit = DEFAULT_LIMIT, pretty = false, db = DEFAULT_DB, allowExtraFunctions = [], throws = true } = {}) {
|
|
7200
7219
|
return (expr) => throws ? privateAgentSql(expr, {
|
|
7201
7220
|
guards,
|
|
7202
7221
|
schema,
|
|
7203
7222
|
limit,
|
|
7223
|
+
pretty,
|
|
7204
7224
|
db,
|
|
7205
7225
|
allowExtraFunctions,
|
|
7206
7226
|
throws
|
|
@@ -7208,12 +7228,13 @@ function createAgentSql(schema, guards, { limit, throws = true, db = "postgres",
|
|
|
7208
7228
|
guards,
|
|
7209
7229
|
schema,
|
|
7210
7230
|
limit,
|
|
7231
|
+
pretty,
|
|
7211
7232
|
db,
|
|
7212
7233
|
allowExtraFunctions,
|
|
7213
7234
|
throws
|
|
7214
7235
|
});
|
|
7215
7236
|
}
|
|
7216
|
-
function privateAgentSql(sql, { guards: guardsRaw, schema, limit, db, allowExtraFunctions, throws }) {
|
|
7237
|
+
function privateAgentSql(sql, { guards: guardsRaw, schema, limit, pretty, db, allowExtraFunctions, throws }) {
|
|
7217
7238
|
const guards = resolveGuards(guardsRaw);
|
|
7218
7239
|
if (!guards.ok) throw guards.error;
|
|
7219
7240
|
const ast = parseSql(sql);
|
|
@@ -7224,7 +7245,7 @@ function privateAgentSql(sql, { guards: guardsRaw, schema, limit, db, allowExtra
|
|
|
7224
7245
|
if (!ast3.ok) return returnOrThrow(ast3, throws);
|
|
7225
7246
|
const san = applyGuards(ast3.data, guards.data, limit);
|
|
7226
7247
|
if (!san.ok) return returnOrThrow(san, throws);
|
|
7227
|
-
const res = outputSql(san.data);
|
|
7248
|
+
const res = outputSql(san.data, pretty);
|
|
7228
7249
|
if (throws) return res;
|
|
7229
7250
|
return Ok(res);
|
|
7230
7251
|
}
|