@checkdigit/eslint-athena-plugin 1.0.0-PR.2-dcdf

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.
Files changed (66) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +17 -0
  3. package/SECURITY.md +13 -0
  4. package/dist-mjs/athena/api-locator.mjs +66 -0
  5. package/dist-mjs/athena/api-matcher.mjs +206 -0
  6. package/dist-mjs/athena/athena.mjs +165 -0
  7. package/dist-mjs/athena/column.mjs +1 -0
  8. package/dist-mjs/athena/context.mjs +21 -0
  9. package/dist-mjs/athena/index.mjs +1 -0
  10. package/dist-mjs/athena/service-table.mjs +45 -0
  11. package/dist-mjs/athena/sql-file.mjs +123 -0
  12. package/dist-mjs/athena/types.mjs +1 -0
  13. package/dist-mjs/athena/validate.mjs +619 -0
  14. package/dist-mjs/athena/visitor.mjs +291 -0
  15. package/dist-mjs/get-documentation-url.mjs +9 -0
  16. package/dist-mjs/index.mjs +56 -0
  17. package/dist-mjs/openapi/deref-schema.mjs +20 -0
  18. package/dist-mjs/openapi/generate-schema.mjs +375 -0
  19. package/dist-mjs/openapi/service-schema-generator.mjs +176 -0
  20. package/dist-mjs/peggy/athena-peggy.mjs +20700 -0
  21. package/dist-mjs/service.mjs +9 -0
  22. package/dist-mjs/sql-parser.mjs +28 -0
  23. package/dist-types/athena/api-locator.d.ts +2 -0
  24. package/dist-types/athena/api-matcher.d.ts +14 -0
  25. package/dist-types/athena/athena.d.ts +5 -0
  26. package/dist-types/athena/column.d.ts +1 -0
  27. package/dist-types/athena/context.d.ts +21 -0
  28. package/dist-types/athena/index.d.ts +8 -0
  29. package/dist-types/athena/service-table.d.ts +8 -0
  30. package/dist-types/athena/sql-file.d.ts +5 -0
  31. package/dist-types/athena/types.d.ts +493 -0
  32. package/dist-types/athena/validate.d.ts +14 -0
  33. package/dist-types/athena/visitor.d.ts +75 -0
  34. package/dist-types/get-documentation-url.d.ts +1 -0
  35. package/dist-types/index.d.ts +5 -0
  36. package/dist-types/openapi/deref-schema.d.ts +1 -0
  37. package/dist-types/openapi/generate-schema.d.ts +33 -0
  38. package/dist-types/openapi/service-schema-generator.d.ts +5 -0
  39. package/dist-types/peggy/athena-peggy.d.ts +13 -0
  40. package/dist-types/service.d.ts +2 -0
  41. package/dist-types/sql-parser.d.ts +25 -0
  42. package/package.json +1 -0
  43. package/src/api/v1/swagger.yml +619 -0
  44. package/src/api/v2/swagger.yml +477 -0
  45. package/src/athena/api-locator.ts +78 -0
  46. package/src/athena/api-matcher.ts +323 -0
  47. package/src/athena/athena.ts +224 -0
  48. package/src/athena/column.ts +4 -0
  49. package/src/athena/context.ts +47 -0
  50. package/src/athena/index.ts +13 -0
  51. package/src/athena/service-table.ts +78 -0
  52. package/src/athena/sql-file.ts +161 -0
  53. package/src/athena/types.ts +568 -0
  54. package/src/athena/validate.ts +902 -0
  55. package/src/athena/visitor.ts +406 -0
  56. package/src/get-documentation-url.ts +7 -0
  57. package/src/index.ts +67 -0
  58. package/src/openapi/deref-schema.ts +20 -0
  59. package/src/openapi/generate-schema.ts +553 -0
  60. package/src/openapi/service-schema-generator.ts +241 -0
  61. package/src/peggy/athena-peggy.ts +22149 -0
  62. package/src/peggy/athena.peggy +2971 -0
  63. package/src/service.ts +11 -0
  64. package/src/services/eslintAthenaPlugin/v1/swagger.schema.deref.json +1931 -0
  65. package/src/services/eslintAthenaPlugin/v2/swagger.schema.deref.json +978 -0
  66. package/src/sql-parser.ts +53 -0
@@ -0,0 +1,9 @@
1
+ // src/service.ts
2
+ import "typescript";
3
+ function isServiceResponse(type) {
4
+ return type.getProperties().some((symbol) => symbol.name === "status") && type.getProperties().some((symbol) => symbol.name === "headers") && type.getProperties().some((symbol) => symbol.name === "body");
5
+ }
6
+ export {
7
+ isServiceResponse
8
+ };
9
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NlcnZpY2UudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBRUEsT0FBZTtBQUVSLFNBQVMsa0JBQWtCLE1BQXdCO0FBQ3hELFNBQ0UsS0FBSyxjQUFjLEVBQUUsS0FBSyxDQUFDLFdBQVcsT0FBTyxTQUFTLFFBQVEsS0FDOUQsS0FBSyxjQUFjLEVBQUUsS0FBSyxDQUFDLFdBQVcsT0FBTyxTQUFTLFNBQVMsS0FDL0QsS0FBSyxjQUFjLEVBQUUsS0FBSyxDQUFDLFdBQVcsT0FBTyxTQUFTLE1BQU07QUFFaEU7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -0,0 +1,28 @@
1
+ // src/sql-parser.ts
2
+ function parseForESLint(code) {
3
+ const lines = code.split("\n");
4
+ return {
5
+ ast: {
6
+ type: "Program",
7
+ body: [],
8
+ sourceType: "module",
9
+ range: [0, code.length],
10
+ loc: {
11
+ start: { line: 1, column: 0 },
12
+ end: {
13
+ line: lines.length,
14
+ column: lines[lines.length - 1]?.length ?? 0
15
+ }
16
+ },
17
+ tokens: [],
18
+ comments: []
19
+ },
20
+ services: {},
21
+ scopeManager: null,
22
+ visitorKeys: { Program: [] }
23
+ };
24
+ }
25
+ export {
26
+ parseForESLint
27
+ };
28
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NxbC1wYXJzZXIudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBOEJPLFNBQVMsZUFBZSxNQUE4QjtBQUMzRCxRQUFNLFFBQVEsS0FBSyxNQUFNLElBQUk7QUFDN0IsU0FBTztBQUFBLElBQ0wsS0FBSztBQUFBLE1BQ0gsTUFBTTtBQUFBLE1BQ04sTUFBTSxDQUFDO0FBQUEsTUFDUCxZQUFZO0FBQUEsTUFDWixPQUFPLENBQUMsR0FBRyxLQUFLLE1BQU07QUFBQSxNQUN0QixLQUFLO0FBQUEsUUFDSCxPQUFPLEVBQUUsTUFBTSxHQUFHLFFBQVEsRUFBRTtBQUFBLFFBQzVCLEtBQUs7QUFBQSxVQUNILE1BQU0sTUFBTTtBQUFBLFVBQ1osUUFBUSxNQUFNLE1BQU0sU0FBUyxDQUFDLEdBQUcsVUFBVTtBQUFBLFFBQzdDO0FBQUEsTUFDRjtBQUFBLE1BQ0EsUUFBUSxDQUFDO0FBQUEsTUFDVCxVQUFVLENBQUM7QUFBQSxJQUNiO0FBQUEsSUFDQSxVQUFVLENBQUM7QUFBQSxJQUNYLGNBQWM7QUFBQSxJQUNkLGFBQWEsRUFBRSxTQUFTLENBQUMsRUFBRTtBQUFBLEVBQzdCO0FBQ0Y7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -0,0 +1,2 @@
1
+ import { type ApiSchemas } from '../openapi/generate-schema.ts';
2
+ export declare function locateApi(originalServiceName: string): ApiSchemas[];
@@ -0,0 +1,14 @@
1
+ import type { SchemaObject } from 'ajv/dist/2020';
2
+ import type { ApiSchemas, OperationSchemas } from '../openapi/generate-schema';
3
+ export interface OperationToMatch {
4
+ path: string;
5
+ method: string;
6
+ operationSchemas: OperationSchemas;
7
+ }
8
+ export interface MatchedOperation {
9
+ path: string;
10
+ method: string;
11
+ request: SchemaObject;
12
+ response: SchemaObject;
13
+ }
14
+ export declare function matchApi(selectAST: object, tableAST: object, apiSchemas: ApiSchemas[]): MatchedOperation[] | undefined;
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ import { ATHENA_ERROR, SYNTAXT_ERROR } from './validate.ts';
3
+ export declare const ruleId = "athena";
4
+ declare const rule: ESLintUtils.RuleModule<typeof SYNTAXT_ERROR | typeof ATHENA_ERROR>;
5
+ export default rule;
@@ -0,0 +1 @@
1
+ export type { ResolvedColumn } from './context';
@@ -0,0 +1,21 @@
1
+ import type { OpenAPIV3_1 as v3 } from 'openapi-types';
2
+ import type { ApiSchemas } from '../openapi/generate-schema';
3
+ import type { MatchedOperation } from './api-matcher';
4
+ export interface ResolvedColumn {
5
+ name: string;
6
+ schema: v3.SchemaObject;
7
+ ast?: object;
8
+ }
9
+ export interface ResolvedTable {
10
+ name?: string;
11
+ columns: Map<string, ResolvedColumn[]>;
12
+ apiOperation?: MatchedOperation[];
13
+ }
14
+ export interface VisitContext {
15
+ tables: Map<string, ResolvedTable[]>;
16
+ aliases: Map<string, string>;
17
+ apiSchemas: Map<string, ApiSchemas[]>;
18
+ parent?: VisitContext;
19
+ }
20
+ export declare function createRootContext(): VisitContext;
21
+ export declare function createChildContext(parent: VisitContext): VisitContext;
@@ -0,0 +1,8 @@
1
+ import type { OpenAPIV3_1 as v3 } from 'openapi-types';
2
+ export interface ServiceEndpoint {
3
+ path: string;
4
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
5
+ requestBody?: v3.SchemaObject;
6
+ responses: Record<string, v3.SchemaObject>;
7
+ }
8
+ export type Service = Record<string, ServiceEndpoint>;
@@ -0,0 +1,8 @@
1
+ import type { MatchedOperation } from './api-matcher';
2
+ import type { ResolvedTable } from './context';
3
+ /**
4
+ * Create one ResolvedTable per matched API operation.
5
+ * Multiple operations may match (e.g. GET + POST for the same service), so the
6
+ * caller receives an array and stores all of them under the same table name.
7
+ */
8
+ export declare function buildServiceTables(tableName: string, operations: MatchedOperation[]): ResolvedTable[];
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ import { ATHENA_ERROR, SYNTAXT_ERROR } from './validate.ts';
3
+ export declare const ruleId = "sql-file";
4
+ declare const rule: ESLintUtils.RuleModule<typeof SYNTAXT_ERROR | typeof ATHENA_ERROR>;
5
+ export default rule;
@@ -0,0 +1,493 @@
1
+ export interface With {
2
+ name: {
3
+ value: string;
4
+ };
5
+ stmt: {
6
+ _parentheses?: boolean;
7
+ tableList: string[];
8
+ columnList: string[];
9
+ ast: Select;
10
+ };
11
+ columns?: any[];
12
+ }
13
+ interface Location {
14
+ line: number;
15
+ column: number;
16
+ offset: number;
17
+ }
18
+ interface LocationRange {
19
+ start: Location;
20
+ end: Location;
21
+ }
22
+ export type WhilteListCheckMode = 'table' | 'column';
23
+ export interface ParseOptions {
24
+ includeLocations?: boolean;
25
+ }
26
+ export interface Option {
27
+ database?: string;
28
+ type?: string;
29
+ trimQuery?: boolean;
30
+ parseOptions?: ParseOptions;
31
+ }
32
+ export interface TableColumnAst {
33
+ tableList: string[];
34
+ columnList: string[];
35
+ ast: AST[] | AST;
36
+ loc?: LocationRange;
37
+ }
38
+ export interface BaseFrom {
39
+ db: string | null;
40
+ table: string;
41
+ as: string | null;
42
+ schema?: string;
43
+ loc?: LocationRange;
44
+ }
45
+ export interface Join extends BaseFrom {
46
+ join: 'INNER JOIN' | 'LEFT JOIN' | 'RIGHT JOIN';
47
+ using?: string[];
48
+ on?: Binary;
49
+ }
50
+ export interface TableExpr {
51
+ expr: {
52
+ ast: Select;
53
+ };
54
+ as?: string | null;
55
+ parentheses: boolean | {
56
+ length: number;
57
+ };
58
+ }
59
+ export interface Dual {
60
+ type: 'dual';
61
+ loc?: LocationRange;
62
+ }
63
+ export interface ValuesFrom {
64
+ expr: {
65
+ type: 'values';
66
+ };
67
+ as: {
68
+ type: 'function';
69
+ name: {
70
+ name: {
71
+ value: string;
72
+ }[];
73
+ };
74
+ args: {
75
+ type: 'expr_list';
76
+ value: {
77
+ column: string;
78
+ }[];
79
+ };
80
+ };
81
+ }
82
+ export type From = BaseFrom | Join | TableExpr | ValuesFrom | Dual;
83
+ export interface LimitValue {
84
+ type: string;
85
+ value: number;
86
+ loc?: LocationRange;
87
+ }
88
+ export interface Limit {
89
+ seperator: string;
90
+ value: LimitValue[];
91
+ loc?: LocationRange;
92
+ }
93
+ export interface OrderBy {
94
+ type: 'ASC' | 'DESC';
95
+ expr: any;
96
+ loc?: LocationRange;
97
+ }
98
+ export interface ValueExpr<T = string | number | boolean> {
99
+ type: 'backticks_quote_string' | 'string' | 'regex_string' | 'hex_string' | 'full_hex_string' | 'natural_string' | 'bit_string' | 'double_quote_string' | 'single_quote_string' | 'boolean' | 'bool' | 'null' | 'star' | 'param' | 'origin' | 'date' | 'datetime' | 'default' | 'time' | 'timestamp' | 'var_string';
100
+ value: T;
101
+ }
102
+ export interface ColumnRefItem {
103
+ type: 'column_ref';
104
+ table: string | null;
105
+ column: string | {
106
+ expr: ValueExpr;
107
+ };
108
+ options?: ExprList;
109
+ loc?: LocationRange;
110
+ }
111
+ export interface ColumnRefExpr {
112
+ type: 'expr';
113
+ expr: ColumnRefItem;
114
+ as: string | null;
115
+ }
116
+ export type ColumnRef = ColumnRefItem | ColumnRefExpr;
117
+ export interface SetList {
118
+ column: string;
119
+ value: any;
120
+ table: string | null;
121
+ loc?: LocationRange;
122
+ }
123
+ export interface InsertReplaceValue {
124
+ type: 'expr_list';
125
+ value: any[];
126
+ loc?: LocationRange;
127
+ }
128
+ export interface Star {
129
+ type: 'star';
130
+ value: '*' | '';
131
+ loc?: LocationRange;
132
+ }
133
+ export interface Case {
134
+ type: 'case';
135
+ expr: null;
136
+ args: ({
137
+ cond: Binary;
138
+ result: ExpressionValue;
139
+ type: 'when';
140
+ } | {
141
+ result: ExpressionValue;
142
+ type: 'else';
143
+ })[];
144
+ }
145
+ export interface Cast {
146
+ type: 'cast';
147
+ keyword: 'cast';
148
+ expr: ExpressionValue;
149
+ symbol: 'as';
150
+ target: {
151
+ dataType: string;
152
+ suffix: unknown[];
153
+ };
154
+ }
155
+ export interface AggrFunc {
156
+ type: 'aggr_func';
157
+ name: string;
158
+ args: {
159
+ expr: ExpressionValue;
160
+ distinct: 'DISTINCT' | null;
161
+ orderby: OrderBy[] | null;
162
+ parentheses?: boolean;
163
+ };
164
+ loc?: LocationRange;
165
+ }
166
+ export interface FunctionName {
167
+ schema?: {
168
+ value: string;
169
+ type: string;
170
+ };
171
+ name: ValueExpr<string>[];
172
+ }
173
+ export interface Function {
174
+ type: 'function';
175
+ name: FunctionName;
176
+ args?: ExprList;
177
+ suffix?: any;
178
+ loc?: LocationRange;
179
+ }
180
+ export interface Column {
181
+ expr: ExpressionValue;
182
+ as: ValueExpr<string> | string | null;
183
+ type?: string;
184
+ loc?: LocationRange;
185
+ }
186
+ export interface Interval {
187
+ type: 'interval';
188
+ unit: string;
189
+ expr: ValueExpr & {
190
+ loc?: LocationRange;
191
+ };
192
+ }
193
+ export interface Param {
194
+ type: 'param';
195
+ value: string;
196
+ loc?: LocationRange;
197
+ }
198
+ export interface Value {
199
+ type: string;
200
+ value: any;
201
+ loc?: LocationRange;
202
+ }
203
+ export interface Binary {
204
+ type: 'binary_expr';
205
+ operator: string;
206
+ left: ExpressionValue | ExprList;
207
+ right: ExpressionValue | ExprList;
208
+ loc?: LocationRange;
209
+ parentheses?: boolean;
210
+ }
211
+ export type Expr = Binary;
212
+ export type ExpressionValue = ColumnRef | Param | Function | Case | AggrFunc | Value | Binary | Cast | Interval;
213
+ export interface ExprList {
214
+ type: 'expr_list';
215
+ value: ExpressionValue[];
216
+ loc?: LocationRange;
217
+ parentheses?: boolean;
218
+ separator?: string;
219
+ }
220
+ export type PartitionBy = {
221
+ type: 'expr';
222
+ expr: ColumnRef[];
223
+ }[];
224
+ export interface WindowSpec {
225
+ name: null;
226
+ partitionby: PartitionBy;
227
+ orderby: OrderBy[] | null;
228
+ window_frame_clause: string | null;
229
+ }
230
+ export type AsWindowSpec = string | {
231
+ window_specification: WindowSpec;
232
+ parentheses: boolean;
233
+ };
234
+ export interface NamedWindowExpr {
235
+ name: string;
236
+ as_window_specification: AsWindowSpec;
237
+ }
238
+ export interface WindowExpr {
239
+ keyword: 'window';
240
+ type: 'window';
241
+ expr: NamedWindowExpr[];
242
+ }
243
+ export interface Select {
244
+ with: With[] | null;
245
+ type: 'select';
246
+ options: any[] | null;
247
+ distinct: 'DISTINCT' | null;
248
+ columns: any[] | Column[];
249
+ from: From[] | TableExpr | null;
250
+ where: Binary | Function | null;
251
+ groupby: {
252
+ columns: ColumnRef[] | undefined;
253
+ modifiers: ValueExpr<string>[];
254
+ } | undefined;
255
+ having: any[] | null;
256
+ orderby: OrderBy[] | null;
257
+ limit: Limit | null;
258
+ window?: WindowExpr;
259
+ qualify?: any[] | null;
260
+ _orderby?: OrderBy[] | null;
261
+ _limit?: Limit | null;
262
+ parentheses_symbol?: boolean;
263
+ _parentheses?: boolean;
264
+ loc?: LocationRange;
265
+ _next?: Select;
266
+ set_op?: string;
267
+ }
268
+ export interface Insert_Replace {
269
+ type: 'replace' | 'insert';
270
+ table: any;
271
+ columns: string[] | null;
272
+ values: InsertReplaceValue[] | Select;
273
+ partition: any[];
274
+ prefix: string;
275
+ on_duplicate_update: {
276
+ keyword: 'on duplicate key update';
277
+ set: SetList[];
278
+ };
279
+ loc?: LocationRange;
280
+ }
281
+ export interface Update {
282
+ type: 'update';
283
+ db: string | null;
284
+ table: (From | Dual)[] | null;
285
+ set: SetList[];
286
+ where: Binary | Function | null;
287
+ loc?: LocationRange;
288
+ }
289
+ export interface Delete {
290
+ type: 'delete';
291
+ table: any;
292
+ from: (From | Dual)[];
293
+ where: Binary | Function | null;
294
+ loc?: LocationRange;
295
+ }
296
+ export interface Alter {
297
+ type: 'alter';
298
+ table: From[];
299
+ expr: any;
300
+ loc?: LocationRange;
301
+ }
302
+ export interface Use {
303
+ type: 'use';
304
+ db: string;
305
+ loc?: LocationRange;
306
+ }
307
+ type KW_UNSIGNED = 'UNSIGNED';
308
+ type KW_ZEROFILL = 'ZEROFILL';
309
+ type Timezone = ['WITHOUT' | 'WITH', 'TIME', 'ZONE'];
310
+ interface KeywordComment {
311
+ type: 'comment';
312
+ keyword: 'comment';
313
+ symbol?: '=';
314
+ value: string;
315
+ }
316
+ interface CollateExpr {
317
+ type: 'collate';
318
+ symbol?: '=';
319
+ value: string;
320
+ }
321
+ interface DataType {
322
+ dataType: string;
323
+ length?: number;
324
+ parentheses?: true;
325
+ suffix?: Timezone | (KW_UNSIGNED | KW_ZEROFILL)[];
326
+ array?: 'one' | 'two';
327
+ }
328
+ interface LiteralNotNull {
329
+ type: 'not null';
330
+ value: 'not null';
331
+ }
332
+ interface LiteralNull {
333
+ type: 'null';
334
+ value: null;
335
+ }
336
+ type LiteralNumeric = number | {
337
+ type: 'bigint';
338
+ value: string;
339
+ };
340
+ interface ColumnConstraint {
341
+ default_val: {
342
+ type: 'default';
343
+ value: any;
344
+ };
345
+ nullable: LiteralNotNull | LiteralNull;
346
+ }
347
+ interface ColumnDefinitionOptList {
348
+ nullable?: ColumnConstraint['nullable'];
349
+ default_val?: ColumnConstraint['default_val'];
350
+ auto_increment?: 'auto_increment';
351
+ unique?: 'unique' | 'unique key';
352
+ primary?: 'key' | 'primary key';
353
+ comment?: KeywordComment;
354
+ collate?: {
355
+ collate: CollateExpr;
356
+ };
357
+ column_format?: {
358
+ column_format: any;
359
+ };
360
+ storage?: {
361
+ storage: any;
362
+ };
363
+ reference_definition?: {
364
+ reference_definition: any;
365
+ };
366
+ character_set?: {
367
+ type: 'CHARACTER SET';
368
+ value: string;
369
+ symbol?: '=';
370
+ };
371
+ }
372
+ type CreateColumnDefinition = {
373
+ column: ColumnRef;
374
+ definition: DataType;
375
+ resource: 'column';
376
+ } & ColumnDefinitionOptList;
377
+ interface IndexType {
378
+ keyword: 'using';
379
+ type: 'btree' | 'hash' | 'gist' | 'gin';
380
+ }
381
+ interface IndexOption {
382
+ type: 'key_block_size';
383
+ symbol?: '=';
384
+ expr: LiteralNumeric;
385
+ }
386
+ interface CreateIndexDefinition {
387
+ index?: string;
388
+ definition: ColumnRef[];
389
+ keyword: 'index' | 'key';
390
+ index_type?: IndexType;
391
+ resource: 'index';
392
+ index_options?: IndexOption[];
393
+ }
394
+ interface CreateFulltextSpatialIndexDefinition {
395
+ index?: string;
396
+ definition: ColumnRef[];
397
+ keyword?: 'fulltext' | 'spatial' | 'fulltext key' | 'spatial key' | 'fulltext index' | 'spatial index';
398
+ index_options?: IndexOption[];
399
+ resource: 'index';
400
+ }
401
+ interface ConstraintName {
402
+ keyword: 'constraint';
403
+ constraint: string;
404
+ }
405
+ interface CreateConstraintPrimary {
406
+ constraint?: ConstraintName['constraint'];
407
+ definition: ColumnRef[];
408
+ constraint_type: 'primary key';
409
+ keyword?: ConstraintName['keyword'];
410
+ index_type?: IndexType;
411
+ resource: 'constraint';
412
+ index_options?: IndexOption[];
413
+ }
414
+ interface CreateConstraintUnique {
415
+ constraint?: ConstraintName['constraint'];
416
+ definition: ColumnRef[];
417
+ constraint_type: 'unique key' | 'unique' | 'unique index';
418
+ keyword?: ConstraintName['keyword'];
419
+ index_type?: IndexType;
420
+ index?: string;
421
+ resource: 'constraint';
422
+ index_options?: IndexOption[];
423
+ }
424
+ interface CreateConstraintForeign {
425
+ constraint?: ConstraintName['constraint'];
426
+ definition: ColumnRef[];
427
+ constraint_type: 'FOREIGN KEY';
428
+ keyword?: ConstraintName['keyword'];
429
+ index?: string;
430
+ resource: 'constraint';
431
+ reference_definition?: any;
432
+ }
433
+ interface CreateConstraintCheck {
434
+ constraint?: ConstraintName['constraint'];
435
+ definition: any[];
436
+ constraint_type: 'check';
437
+ keyword?: ConstraintName['keyword'];
438
+ resource: 'constraint';
439
+ }
440
+ type CreateConstraintDefinition = CreateConstraintPrimary | CreateConstraintUnique | CreateConstraintForeign | CreateConstraintCheck;
441
+ type CreateDefinition = CreateColumnDefinition | CreateIndexDefinition | CreateFulltextSpatialIndexDefinition | CreateConstraintDefinition;
442
+ export interface Create {
443
+ type: 'create';
444
+ keyword: 'table' | 'index' | 'database';
445
+ temporary?: 'temporary' | null;
446
+ table?: {
447
+ db: string;
448
+ table: string;
449
+ }[];
450
+ if_not_exists?: 'if not exists' | null;
451
+ like?: {
452
+ type: 'like';
453
+ table: string;
454
+ parentheses?: boolean;
455
+ } | null;
456
+ ignore_replace?: 'ignore' | 'replace' | null;
457
+ as?: string | null;
458
+ query_expr?: any | null;
459
+ create_definitions?: CreateDefinition[] | null;
460
+ table_options?: any[] | null;
461
+ index_using?: {
462
+ keyword: 'using';
463
+ type: 'btree' | 'hash';
464
+ } | null;
465
+ index?: string | null;
466
+ on_kw?: 'on' | null;
467
+ index_columns?: any[] | null;
468
+ index_type?: 'unique' | 'fulltext' | 'spatial' | null;
469
+ index_options?: any[] | null;
470
+ algorithm_option?: {
471
+ type: 'alter';
472
+ keyword: 'algorithm';
473
+ resource: 'algorithm';
474
+ symbol: '=' | null;
475
+ algorithm: 'default' | 'instant' | 'inplace' | 'copy';
476
+ } | null;
477
+ lock_option?: {
478
+ type: 'alter';
479
+ keyword: 'lock';
480
+ resource: 'lock';
481
+ symbol: '=' | null;
482
+ lock: 'default' | 'none' | 'shared' | 'exclusive';
483
+ } | null;
484
+ database?: string;
485
+ loc?: LocationRange;
486
+ }
487
+ export interface Drop {
488
+ type: 'drop';
489
+ keyword: string;
490
+ name: any[];
491
+ }
492
+ export type AST = Use | Select | Insert_Replace | Update | Delete | Alter | Create | Drop;
493
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { AST } from './types';
2
+ import { type VisitContext } from './context.ts';
3
+ export declare const SYNTAXT_ERROR = "SyntaxError";
4
+ export declare const ATHENA_ERROR = "AthenaError";
5
+ export declare class AthenaError extends Error {
6
+ code: string;
7
+ ast?: object;
8
+ constructor(code: string, message: string, ast?: object);
9
+ }
10
+ export declare function offsetToLoc(text: string, offset: number): {
11
+ line: number;
12
+ column: number;
13
+ };
14
+ export declare function checkAthenaAst(ast: AST, ctx: VisitContext): void;
@@ -0,0 +1,75 @@
1
+ import type { AggrFunc, BaseFrom, Binary, Case, Cast, Column, ColumnRefItem, Dual, ExpressionValue, ExprList, From, Function, Join, Select, TableExpr, ValuesFrom, With } from './types';
2
+ export interface UnnestFrom {
3
+ type: 'unnest';
4
+ expr: ColumnRefItem | {
5
+ type: string;
6
+ };
7
+ parentheses: boolean;
8
+ as: {
9
+ type: 'function';
10
+ name: {
11
+ name: {
12
+ type: string;
13
+ value: string;
14
+ }[];
15
+ };
16
+ args: ExprList;
17
+ } | null;
18
+ }
19
+ export interface ColumnRefWithIndex extends ColumnRefItem {
20
+ array_index: {
21
+ brackets: true;
22
+ index: {
23
+ type: string;
24
+ value: unknown;
25
+ };
26
+ }[];
27
+ }
28
+ export interface VisitorMap {
29
+ visitSelect?(node: Select): void;
30
+ visitWith?(node: With): void;
31
+ visitBaseFrom?(node: BaseFrom): void;
32
+ visitJoin?(node: Join): void;
33
+ visitTableExpr?(node: TableExpr): void;
34
+ visitUnnest?(node: UnnestFrom): void;
35
+ visitColumn?(node: Column): void;
36
+ visitColumnRef?(node: ColumnRefItem): void;
37
+ visitFunction?(node: Function): void;
38
+ visitBinary?(node: Binary): void;
39
+ visitAggrFunc?(node: AggrFunc): void;
40
+ visitCast?(node: Cast): void;
41
+ visitCase?(node: Case): void;
42
+ visitExprList?(node: ExprList): void;
43
+ visitValue?(node: ExpressionValue): void;
44
+ }
45
+ export declare function isUnnestFrom(node: unknown): node is UnnestFrom;
46
+ export declare function isDual(node: unknown): node is Dual;
47
+ export declare function isValuesFrom(node: unknown): node is ValuesFrom;
48
+ export declare function isTableExpr(node: unknown): node is TableExpr;
49
+ export declare function isJoin(node: unknown): node is Join;
50
+ export declare function isBaseFrom(node: unknown): node is BaseFrom;
51
+ export declare function hasArrayIndex(node: ColumnRefItem): node is ColumnRefWithIndex;
52
+ /** Normalise select.from (null / single item / array) to a From[]. */
53
+ export declare function fromClauseItems(select: Select): From[];
54
+ export declare function walk(node: unknown, visitor: VisitorMap): void;
55
+ /** Return true if the expression contains a lambda (`->`) subexpression. */
56
+ export declare function containsLambda(expr: unknown): boolean;
57
+ /** Collect all column_ref nodes within an expression subtree. */
58
+ export declare function extractColumnRefs(expr: unknown): ColumnRefItem[];
59
+ export interface JsonExtractCall {
60
+ ref: ColumnRefItem;
61
+ path: string;
62
+ fnNode: Function;
63
+ }
64
+ /** Collect ALL json_extract / json_extract_scalar calls as (source column_ref, path) pairs. */
65
+ export declare function extractJsonExtractCalls(expr: unknown): JsonExtractCall[];
66
+ /** Return the path string from the first json_extract_scalar / json_extract call found. */
67
+ export declare function extractJsonExtractPath(expr: unknown): string | undefined;
68
+ /** Return the JSONPath-style string from a bracket accessor (col['key']), or undefined. */
69
+ export declare function extractBracketAccessorPath(expr: unknown): string | undefined;
70
+ /** Return true if the expression tree contains any function or aggregate call. */
71
+ export declare function hasFunctionCalls(expr: unknown): boolean;
72
+ /** Return true when the expression tree contains any CAST / TRY_CAST to ARRAY<…>. */
73
+ export declare function containsCastToArray(expr: unknown): boolean;
74
+ /** Return true when the expression tree contains any CAST / TRY_CAST to MAP<…>. */
75
+ export declare function containsCastToMap(expr: unknown): boolean;