sqyrl 0.0.2 → 0.1.1

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/README.md CHANGED
@@ -15,15 +15,17 @@ npm install sqyrl
15
15
  ```ts
16
16
  import { sqyrl } from "sqyrl";
17
17
 
18
- const sql = sqyrl(`SELECT id, name FROM public.users WHERE status = 'active' LIMIT 10`, {
19
- schema: "public",
18
+ const sql = sqyrl(`SELECT id, name FROM users WHERE status = 'active' LIMIT 10`, {
20
19
  table: "users",
21
20
  column: "tenant_id",
22
21
  value: "acme",
23
22
  });
24
23
 
25
24
  console.log(sql);
26
- // SELECT id, name FROM public.users WHERE public.users.tenant_id = 'acme' AND status = 'active' LIMIT 10
25
+ // SELECT id, name
26
+ // FROM public.users
27
+ // WHERE users.tenant_id = 'acme'
28
+ // AND status = 'active' LIMIT 10
27
29
  ```
28
30
 
29
31
  `sqyrl` parses the SQL, enforces a mandatory equality filter on the given column as the outermost `AND` condition (so it cannot be short-circuited by agent-supplied `OR` clauses), and returns the sanitised SQL string.
@@ -35,12 +37,24 @@ console.log(sql);
35
37
 
36
38
  ## Development
37
39
 
40
+ First install [Vite+](https://viteplus.dev/guide/):
41
+
42
+ ```bash
43
+ curl -fsSL https://vite.plus | bash
44
+ ```
45
+
38
46
  Install dependencies:
39
47
 
40
48
  ```bash
41
49
  vp install
42
50
  ```
43
51
 
52
+ Format, lint, typecheck:
53
+
54
+ ```bash
55
+ vp check --fix
56
+ ```
57
+
44
58
  Run the unit tests:
45
59
 
46
60
  ```bash
package/dist/index.d.mts CHANGED
@@ -1,44 +1,217 @@
1
1
  //#region src/ast.d.ts
2
2
  interface SelectStatement {
3
- type: "select";
3
+ readonly type: "select";
4
+ distinct: Distinct | null;
4
5
  columns: Column[];
5
- from: TableRef;
6
- where: WhereExpr | null;
7
- limit: number | null;
6
+ from: SelectFrom;
7
+ joins: JoinClause[];
8
+ where: WhereRoot | null;
9
+ groupBy: GroupByClause | null;
10
+ having: HavingClause | null;
11
+ orderBy: OrderByClause | null;
12
+ limit: LimitClause | null;
13
+ offset: OffsetClause | null;
8
14
  }
9
- type WhereExpr = WhereAnd | WhereOr | WhereComparison;
15
+ interface Distinct {
16
+ readonly type: "distinct";
17
+ }
18
+ interface GroupByClause {
19
+ readonly type: "group_by";
20
+ items: WhereValue[];
21
+ }
22
+ interface HavingClause {
23
+ readonly type: "having";
24
+ expr: WhereExpr;
25
+ }
26
+ interface OrderByClause {
27
+ readonly type: "order_by";
28
+ items: OrderByItem[];
29
+ }
30
+ type SortDirection = "asc" | "desc";
31
+ type NullsOrder = "nulls_first" | "nulls_last";
32
+ interface OrderByItem {
33
+ readonly type: "order_by_item";
34
+ expr: WhereValue;
35
+ direction?: SortDirection;
36
+ nulls?: NullsOrder;
37
+ }
38
+ interface OffsetClause {
39
+ readonly type: "offset";
40
+ value: number;
41
+ }
42
+ type JoinType = "inner" | "inner_outer" | "left" | "left_outer" | "right" | "right_outer" | "full" | "full_outer" | "cross" | "natural";
43
+ type JoinCondition = {
44
+ readonly type: "join_on";
45
+ expr: WhereExpr;
46
+ } | {
47
+ readonly type: "join_using";
48
+ columns: string[];
49
+ };
50
+ interface JoinClause {
51
+ readonly type: "join";
52
+ joinType: JoinType;
53
+ table: TableRef;
54
+ condition: JoinCondition | null;
55
+ }
56
+ type SelectFrom = {
57
+ readonly type: "select_from";
58
+ table: TableRef;
59
+ };
60
+ type LimitClause = {
61
+ readonly type: "limit";
62
+ value: number;
63
+ };
64
+ type WhereRoot = {
65
+ readonly type: "where_root";
66
+ inner: WhereExpr;
67
+ };
68
+ type WhereExpr = WhereAnd | WhereOr | WhereNot | WhereComparison | WhereIsNull | WhereIsBool | WhereBetween | WhereIn | WhereLike;
10
69
  interface WhereAnd {
11
- type: "and";
70
+ readonly type: "where_and";
12
71
  left: WhereExpr;
13
72
  right: WhereExpr;
14
73
  }
15
74
  interface WhereOr {
16
- type: "or";
75
+ readonly type: "where_or";
17
76
  left: WhereExpr;
18
77
  right: WhereExpr;
19
78
  }
20
- interface WhereComparison {
21
- type: "comparison";
22
- operator: "=";
23
- column: ColumnRefNode;
79
+ type ComparisonOperator = "=" | "<>" | "!=" | "<" | ">" | "<=" | ">=";
80
+ interface WhereNot {
81
+ readonly type: "where_not";
82
+ expr: WhereExpr;
83
+ }
84
+ interface WhereIsNull {
85
+ readonly type: "where_is_null";
86
+ not: boolean;
87
+ expr: WhereValue;
88
+ }
89
+ type IsBoolTarget = boolean | "unknown";
90
+ interface WhereIsBool {
91
+ readonly type: "where_is_bool";
92
+ not: boolean;
93
+ expr: WhereValue;
94
+ target: IsBoolTarget;
95
+ }
96
+ interface WhereBetween {
97
+ readonly type: "where_between";
98
+ not: boolean;
99
+ expr: WhereValue;
100
+ low: WhereValue;
101
+ high: WhereValue;
102
+ }
103
+ interface WhereIn {
104
+ readonly type: "where_in";
105
+ not: boolean;
106
+ expr: WhereValue;
107
+ list: WhereValue[];
108
+ }
109
+ type LikeOp = "like";
110
+ interface WhereLike {
111
+ readonly type: "where_like";
112
+ not: boolean;
113
+ op: LikeOp;
114
+ expr: WhereValue;
115
+ pattern: WhereValue;
116
+ }
117
+ type ArithOp = "+" | "-" | "*" | "/" | "%" | "||";
118
+ interface WhereArith {
119
+ readonly type: "where_arith";
120
+ op: ArithOp;
121
+ left: WhereValue;
122
+ right: WhereValue;
123
+ }
124
+ interface WhereUnaryMinus {
125
+ readonly type: "where_unary_minus";
126
+ expr: WhereValue;
127
+ }
128
+ interface CaseWhen {
129
+ condition: WhereValue;
130
+ result: WhereValue;
131
+ }
132
+ interface CaseExpr {
133
+ readonly type: "case_expr";
134
+ subject: WhereValue | null;
135
+ whens: CaseWhen[];
136
+ else: WhereValue | null;
137
+ }
138
+ interface CastExpr {
139
+ readonly type: "cast_expr";
140
+ expr: WhereValue;
141
+ typeName: string;
142
+ }
143
+ type WhereValue = {
144
+ readonly type: "where_value";
145
+ kind: "string";
24
146
  value: string;
147
+ } | {
148
+ readonly type: "where_value";
149
+ kind: "integer";
150
+ value: number;
151
+ } | {
152
+ readonly type: "where_value";
153
+ kind: "float";
154
+ value: number;
155
+ } | {
156
+ readonly type: "where_value";
157
+ kind: "bool";
158
+ value: boolean;
159
+ } | {
160
+ readonly type: "where_value";
161
+ kind: "null";
162
+ } | {
163
+ readonly type: "where_value";
164
+ kind: "column_ref";
165
+ ref: ColumnRef;
166
+ } | {
167
+ readonly type: "where_value";
168
+ kind: "func_call";
169
+ func: FuncCall;
170
+ } | WhereArith | WhereUnaryMinus | CaseExpr | CastExpr;
171
+ interface WhereComparison {
172
+ readonly type: "where_comparison";
173
+ operator: ComparisonOperator;
174
+ left: WhereValue;
175
+ right: WhereValue;
25
176
  }
26
- interface ColumnRefNode {
27
- type: "column_ref";
177
+ interface ColumnRef {
178
+ readonly type: "column_ref";
179
+ schema?: string;
28
180
  table?: string;
29
181
  name: string;
30
182
  }
31
- interface Column {
32
- type: "wildcard" | "qualified_wildcard" | "qualified" | "simple";
183
+ type FuncCallArg = {
184
+ kind: "wildcard";
185
+ } | {
186
+ kind: "args";
187
+ distinct: boolean;
188
+ args: WhereValue[];
189
+ };
190
+ interface FuncCall {
191
+ readonly type: "func_call";
192
+ name: string;
193
+ args: FuncCallArg;
194
+ }
195
+ interface ColumnExpr {
196
+ readonly type: "column_expr";
197
+ kind: "wildcard" | "qualified_wildcard" | "expr";
33
198
  table?: string;
34
- name?: string;
35
- alias?: string;
199
+ expr?: WhereValue;
200
+ }
201
+ interface Column {
202
+ readonly type: "column";
203
+ expr: ColumnExpr;
204
+ alias?: Alias;
205
+ }
206
+ interface Alias {
207
+ readonly type: "alias";
208
+ name: string;
36
209
  }
37
210
  interface TableRef {
38
- type: "table";
211
+ readonly type: "table_ref";
39
212
  schema?: string;
40
213
  name: string;
41
- alias?: string;
214
+ alias?: Alias;
42
215
  }
43
216
  //#endregion
44
217
  //#region src/output.d.ts
@@ -48,31 +221,20 @@ declare function outputSql(ast: SelectStatement): string;
48
221
  declare function parseSql(expr: string): SelectStatement;
49
222
  //#endregion
50
223
  //#region src/sanitise.d.ts
51
- declare function sanitiseSql({
52
- ast,
224
+ interface WhereGuard {
225
+ schema?: string;
226
+ table: string;
227
+ col: string;
228
+ value: string | number;
229
+ }
230
+ declare function sanitiseSql(ast: SelectStatement, {
53
231
  schema,
54
232
  table,
55
233
  col,
56
234
  value
57
- }: {
58
- ast: SelectStatement;
59
- schema: string;
60
- table: string;
61
- col: string;
62
- value: string;
63
- }): SelectStatement;
235
+ }: WhereGuard): SelectStatement;
64
236
  //#endregion
65
237
  //#region src/index.d.ts
66
- declare function sqyrl(expr: string, {
67
- schema,
68
- table,
69
- column,
70
- value
71
- }: {
72
- schema: string;
73
- table: string;
74
- column: string;
75
- value: string;
76
- }): string;
238
+ declare function sqyrl(expr: string, whereGuard: WhereGuard): string;
77
239
  //#endregion
78
240
  export { outputSql, parseSql, sanitiseSql, sqyrl };