@checkdigit/eslint-plugin 7.18.0-PR.143-8290 → 7.18.0-PR.143-0de2

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.
@@ -1,103 +1,193 @@
1
1
  // src/athena/api-matcher.ts
2
2
  import debug from "debug";
3
- import { JSONPath } from "jsonpath-plus";
4
3
  var log = debug("eslint-plugin:athena:api-matcher");
5
- function getVersionMatcher(_selectAST, _tableAST) {
6
- return void 0;
4
+ var ALWAYS_TRUE = () => true;
5
+ function rec(node) {
6
+ return typeof node === "object" && node !== null ? node : void 0;
7
7
  }
8
- function getPathPartMatcher(selectAST, _tableAST) {
9
- const [pathPartCondition] = JSONPath({
10
- json: selectAST,
11
- path: "$.where..[?(@ && @.type === 'binary_expr' && @.operator === '=' && @.left && @.left.type === 'function' && @.left.name && @.left.name.name && @.left.name.name[0] && @.left.name.name[0].value === 'split' && @.left.args && @.left.args.value && @.left.args.value[0] && @.left.args.value[0].type === 'column_ref' && @.left.args.value[0].column === 'url' && @.left.args.value[1] && @.left.args.value[1].type === 'single_quote_string' && @.left.args.value[1].value === '/' && @.left.array_index && @.left.array_index[0] && @.left.array_index[0].brackets === true && @.left.array_index[0].index && @.left.array_index[0].index.type === 'number')]"
12
- });
13
- if (pathPartCondition !== void 0) {
14
- const [pathPartIndex] = JSONPath({
15
- json: pathPartCondition,
16
- path: "$.left.array_index[0].index.value"
17
- });
18
- const [pathPartMatch] = JSONPath({
19
- json: pathPartCondition,
20
- path: "$.right.value"
21
- });
22
- return (path, _method) => {
23
- const parts = path.split("/");
24
- const part = parts[pathPartIndex - 1];
25
- log(`checking path part`, { path, pathPartIndex, part, pathPartMatch });
26
- return part?.startsWith(":") === true ? true : parts[pathPartIndex - 1] === pathPartMatch;
27
- };
8
+ function getFunctionName(node) {
9
+ const fn = rec(node);
10
+ if (fn?.["type"] !== "function") {
11
+ return void 0;
28
12
  }
29
- return void 0;
13
+ const name = fn["name"];
14
+ const firstName = name?.name[0];
15
+ return firstName === void 0 ? void 0 : firstName.value.toLowerCase();
30
16
  }
31
- function getPathPartsCountMatcher(selectAST, _tableAST) {
32
- const [pathPartCount] = JSONPath({
33
- json: selectAST,
34
- path: "$.where..[?(@ && @.type === 'binary_expr' && @.operator === '=' && @.left && @.left.type === 'function' && @.left.name && @.left.name.name && @.left.name.name[0] && @.left.name.name[0].value === 'cardinality' && @.right && @.right.type === 'number' && @.left.args && @.left.args.value && @.left.args.value[0] && @.left.args.value[0].type === 'function' && @.left.args.value[0].name && @.left.args.value[0].name.name && @.left.args.value[0].name.name[0] && @.left.args.value[0].name.name[0].value === 'split' && @.left.args.value[0].args && @.left.args.value[0].args.value && @.left.args.value[0].args.value[0] && @.left.args.value[0].args.value[0].type === 'column_ref' && @.left.args.value[0].args.value[0].column === 'url' && @.left.args.value[0].args.value[1] && @.left.args.value[0].args.value[1].type === 'single_quote_string' && @.left.args.value[0].args.value[1].value === '/')].right.value"
35
- });
36
- if (pathPartCount !== void 0) {
37
- return (path, _method) => {
38
- const parts = path.split("/");
39
- return parts.length === pathPartCount;
40
- };
17
+ function getColumnName(node) {
18
+ const col = rec(node);
19
+ if (col?.["type"] !== "column_ref") {
20
+ return void 0;
41
21
  }
42
- return void 0;
22
+ const column = node.column;
23
+ return typeof column === "string" ? column.toLowerCase() : void 0;
24
+ }
25
+ function getColumnTable(node) {
26
+ const col = rec(node);
27
+ if (col?.["type"] !== "column_ref") {
28
+ return void 0;
29
+ }
30
+ return node.table;
31
+ }
32
+ function getStringValue(node) {
33
+ const val = rec(node);
34
+ if (val?.["type"] !== "single_quote_string" && val?.["type"] !== "string") {
35
+ return void 0;
36
+ }
37
+ return typeof val["value"] === "string" ? val["value"] : void 0;
38
+ }
39
+ function getNumberValue(node) {
40
+ const val = rec(node);
41
+ return val?.["type"] === "number" && typeof val["value"] === "number" ? val["value"] : void 0;
42
+ }
43
+ function isSplitUrlIndexed(node) {
44
+ const fn = rec(node);
45
+ if (fn?.["type"] !== "function") {
46
+ return false;
47
+ }
48
+ if (getFunctionName(node) !== "split") {
49
+ return false;
50
+ }
51
+ const args = fn["args"]?.value;
52
+ if (!Array.isArray(args) || args.length < 2) {
53
+ return false;
54
+ }
55
+ if (getColumnName(args[0]) !== "url") {
56
+ return false;
57
+ }
58
+ if (getStringValue(args[1]) !== "/") {
59
+ return false;
60
+ }
61
+ return Array.isArray(fn["array_index"]) && fn["array_index"].length > 0;
62
+ }
63
+ function isCardinalitySplitUrl(node) {
64
+ const fn = rec(node);
65
+ if (fn?.["type"] !== "function") {
66
+ return false;
67
+ }
68
+ if (getFunctionName(node) !== "cardinality") {
69
+ return false;
70
+ }
71
+ const outerArgs = fn["args"]?.value;
72
+ if (!Array.isArray(outerArgs) || outerArgs.length === 0) {
73
+ return false;
74
+ }
75
+ const innerFn = rec(outerArgs[0]);
76
+ if (innerFn?.["type"] !== "function") {
77
+ return false;
78
+ }
79
+ if (getFunctionName(outerArgs[0]) !== "split") {
80
+ return false;
81
+ }
82
+ const innerArgs = innerFn["args"]?.value;
83
+ if (!Array.isArray(innerArgs) || innerArgs.length < 2) {
84
+ return false;
85
+ }
86
+ return getColumnName(innerArgs[0]) === "url" && getStringValue(innerArgs[1]) === "/";
43
87
  }
44
- function getPathMatchers(selectAST, tableAST) {
45
- return [getPathPartMatcher(selectAST, tableAST), getPathPartsCountMatcher(selectAST, tableAST)];
88
+ function getConditionTableQualifier(left) {
89
+ const colName = getColumnName(left);
90
+ if (colName !== void 0) {
91
+ return getColumnTable(left);
92
+ }
93
+ if (isSplitUrlIndexed(left)) {
94
+ const args = rec(left)?.["args"]?.value;
95
+ return getColumnTable(args?.[0]) ?? null;
96
+ }
97
+ if (isCardinalitySplitUrl(left)) {
98
+ const outerArgs = rec(left)?.["args"]?.value;
99
+ const splitFn = rec(outerArgs?.[0]);
100
+ const innerArgs = splitFn?.["args"]?.value;
101
+ return getColumnTable(innerArgs?.[0]) ?? null;
102
+ }
103
+ return void 0;
46
104
  }
47
- function getMethodMatcher(selectAST, _tableAST) {
48
- const [methodToMatch] = JSONPath({
49
- json: selectAST,
50
- path: "$.where..[?(@ && @.type === 'binary_expr' && @.operator === '=' && @.left && @.left.type === 'column_ref' && @.left.column === 'method' && @.right && @.right.type === 'single_quote_string')].right.value"
51
- });
52
- if (methodToMatch !== void 0) {
53
- return (_path, method) => method === methodToMatch;
105
+ function buildLeafPredicate(node, tableAlias) {
106
+ if (node.operator !== "=") {
107
+ return void 0;
108
+ }
109
+ const { left, right } = node;
110
+ const conditionTable = getConditionTableQualifier(left);
111
+ if (conditionTable !== null && conditionTable !== void 0 && tableAlias !== null && conditionTable !== tableAlias) {
112
+ return void 0;
113
+ }
114
+ if (getColumnName(left) === "method") {
115
+ const value = getStringValue(right);
116
+ if (value !== void 0) {
117
+ return (_path, method) => method === value;
118
+ }
119
+ }
120
+ if (getColumnName(left) === "responsestatus") {
121
+ const value = getStringValue(right);
122
+ if (value !== void 0) {
123
+ return (_path, _method, responseCode) => responseCode === value;
124
+ }
125
+ }
126
+ if (isSplitUrlIndexed(left)) {
127
+ const index = left.array_index[0]?.index.value;
128
+ const value = getStringValue(right);
129
+ if (typeof index === "number" && value !== void 0) {
130
+ return (path) => {
131
+ const parts = path.split("/");
132
+ const part = parts[index - 1];
133
+ log(`checking path part`, { path, index, part, value });
134
+ return part?.startsWith(":") === true ? true : part === value;
135
+ };
136
+ }
137
+ }
138
+ if (isCardinalitySplitUrl(left)) {
139
+ const count = getNumberValue(right);
140
+ if (count !== void 0) {
141
+ return (path) => path.split("/").length === count;
142
+ }
54
143
  }
55
144
  return void 0;
56
145
  }
57
- function getResponseStatusToMatch(selectAST, _tableAST) {
58
- const [responseStatus] = JSONPath({
59
- json: selectAST,
60
- path: "$.where..[?(@ && @.type === 'binary_expr' && @.operator === '=' && @.left && @.left.type === 'column_ref' && @.left.column === 'responsestatus' && @.right && @.right.type === 'single_quote_string')].right.value"
61
- });
62
- return responseStatus;
146
+ function buildPredicate(expr, tableAlias) {
147
+ const node = rec(expr);
148
+ if (node?.["type"] !== "binary_expr") {
149
+ return ALWAYS_TRUE;
150
+ }
151
+ const binary = expr;
152
+ switch (binary.operator) {
153
+ case "AND": {
154
+ const leftPred = buildPredicate(binary.left, tableAlias);
155
+ const rightPred = buildPredicate(binary.right, tableAlias);
156
+ return (path, method, code) => leftPred(path, method, code) && rightPred(path, method, code);
157
+ }
158
+ case "OR": {
159
+ const leftPred = buildPredicate(binary.left, tableAlias);
160
+ const rightPred = buildPredicate(binary.right, tableAlias);
161
+ return (path, method, code) => leftPred(path, method, code) || rightPred(path, method, code);
162
+ }
163
+ case "NOT": {
164
+ const innerPred = buildPredicate(binary.left, tableAlias);
165
+ return (path, method, code) => !innerPred(path, method, code);
166
+ }
167
+ default: {
168
+ return buildLeafPredicate(binary, tableAlias) ?? ALWAYS_TRUE;
169
+ }
170
+ }
63
171
  }
64
172
  function matchApi(selectAST, tableAST, apiSchemas) {
65
- const schemaMatchers = [
66
- getVersionMatcher(selectAST, tableAST),
67
- getPathMatchers(selectAST, tableAST),
68
- getMethodMatcher(selectAST, tableAST)
69
- ].flat().filter((matcher) => matcher !== void 0);
70
- const allOperationSchemas = apiSchemas.flatMap((apiSchema) => Object.entries(apiSchema.apis)).flatMap(
173
+ const tableAlias = tableAST.as ?? null;
174
+ const predicate = buildPredicate(selectAST.where ?? null, tableAlias);
175
+ const allOperations = apiSchemas.flatMap((apiSchema) => Object.entries(apiSchema.apis)).flatMap(
71
176
  ([path, operations]) => Object.entries(operations).map(([method, operationSchemas]) => ({
72
177
  path,
73
178
  method: method.toUpperCase(),
74
179
  operationSchemas
75
180
  }))
76
181
  );
77
- log("total operation schemas", allOperationSchemas.length);
78
- const matchedOperationSchemas = allOperationSchemas.filter(
79
- ({ path, method }) => schemaMatchers.every((matcher) => matcher(path, method))
182
+ log("total operation schemas", allOperations.length);
183
+ const matchedApis = allOperations.flatMap(
184
+ ({ path, method, operationSchemas }) => Object.entries(operationSchemas.responses).flatMap(
185
+ ([responseCode, responseSchema]) => predicate(path, method, responseCode) ? [{ path, method, request: operationSchemas.request, response: responseSchema }] : []
186
+ )
80
187
  );
81
- log("matched operation schemas", matchedOperationSchemas.length);
82
- if (matchedOperationSchemas.length === 0) {
83
- log("no matched operation schema");
84
- throw new Error("no matched operation schema");
85
- }
86
- const matchedResponseStatus = getResponseStatusToMatch(selectAST, tableAST);
87
- log("matchedResponseStatus", matchedResponseStatus);
88
- const matchedApis = matchedOperationSchemas.flatMap(
89
- (operation) => Object.entries(operation.operationSchemas.responses).map(([responseCode, responseSchema]) => {
90
- const matchedResponseSchema = matchedResponseStatus === void 0 || responseCode === matchedResponseStatus ? responseSchema : void 0;
91
- return matchedResponseSchema === void 0 ? void 0 : {
92
- path: operation.path,
93
- method: operation.method,
94
- request: operation.operationSchemas.request,
95
- response: matchedResponseSchema
96
- };
97
- })
98
- ).filter((api) => api !== void 0);
188
+ log("matched apis", matchedApis.length);
99
189
  if (matchedApis.length === 0) {
100
- log("no api satisfy both request and response matchers");
190
+ log("no matched api");
101
191
  throw new Error("no matched api");
102
192
  }
103
193
  return matchedApis;
@@ -105,4 +195,4 @@ function matchApi(selectAST, tableAST, apiSchemas) {
105
195
  export {
106
196
  matchApi
107
197
  };
108
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hcGktbWF0Y2hlci50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFFQSxPQUFPLFdBQVc7QUFDbEIsU0FBUyxnQkFBZ0I7QUFLekIsSUFBTSxNQUFNLE1BQU0sa0NBQWtDO0FBa0JwRCxTQUFTLGtCQUFrQixZQUFvQixXQUF3QztBQUNyRixTQUFPO0FBQ1Q7QUFHQSxTQUFTLG1CQUFtQixXQUFtQixXQUF3QztBQUNyRixRQUFNLENBQUMsaUJBQWlCLElBQWMsU0FBUztBQUFBLElBQzdDLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxFQUNSLENBQUM7QUFHRCxNQUFJLHNCQUFzQixRQUFXO0FBQ25DLFVBQU0sQ0FBQyxhQUFhLElBQWMsU0FBUztBQUFBLE1BQ3pDLE1BQU07QUFBQSxNQUNOLE1BQU07QUFBQSxJQUNSLENBQUM7QUFDRCxVQUFNLENBQUMsYUFBYSxJQUFjLFNBQVM7QUFBQSxNQUN6QyxNQUFNO0FBQUEsTUFDTixNQUFNO0FBQUEsSUFDUixDQUFDO0FBRUQsV0FBTyxDQUFDLE1BQWMsWUFBb0I7QUFDeEMsWUFBTSxRQUFRLEtBQUssTUFBTSxHQUFHO0FBQzVCLFlBQU0sT0FBTyxNQUFNLGdCQUFnQixDQUFDO0FBQ3BDLFVBQUksc0JBQXNCLEVBQUUsTUFBTSxlQUFlLE1BQU0sY0FBYyxDQUFDO0FBQ3RFLGFBQU8sTUFBTSxXQUFXLEdBQUcsTUFBTSxPQUM3QixPQUNBLE1BQU0sZ0JBQWdCLENBQUMsTUFBTTtBQUFBLElBQ25DO0FBQUEsRUFDRjtBQUVBLFNBQU87QUFDVDtBQUdBLFNBQVMseUJBQXlCLFdBQW1CLFdBQXdDO0FBRTNGLFFBQU0sQ0FBQyxhQUFhLElBQWMsU0FBUztBQUFBLElBQ3pDLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxFQUNSLENBQUM7QUFFRCxNQUFJLGtCQUFrQixRQUFXO0FBRS9CLFdBQU8sQ0FBQyxNQUFjLFlBQW9CO0FBQ3hDLFlBQU0sUUFBUSxLQUFLLE1BQU0sR0FBRztB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
198
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hcGktbWF0Y2hlci50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFFQSxPQUFPLFdBQVc7QUFNbEIsSUFBTSxNQUFNLE1BQU0sa0NBQWtDO0FBa0JwRCxJQUFNLGNBQWtDLE1BQU07QUFJOUMsU0FBUyxJQUFJLE1BQW9EO0FBQy9ELFNBQU8sT0FBTyxTQUFTLFlBQVksU0FBUyxPQUFRLE9BQW1DO0FBQ3pGO0FBRUEsU0FBUyxnQkFBZ0IsTUFBbUM7QUFDMUQsUUFBTSxLQUFLLElBQUksSUFBSTtBQUNuQixNQUFJLEtBQUssTUFBTSxNQUFNLFlBQVk7QUFDL0IsV0FBTztBQUFBLEVBQ1Q7QUFDQSxRQUFNLE9BQU8sR0FBRyxNQUFNO0FBQ3RCLFFBQU0sWUFBWSxNQUFNLEtBQUssQ0FBQztBQUM5QixTQUFPLGNBQWMsU0FBWSxTQUFZLFVBQVUsTUFBTSxZQUFZO0FBQzNFO0FBRUEsU0FBUyxjQUFjLE1BQW1DO0FBQ3hELFFBQU0sTUFBTSxJQUFJLElBQUk7QUFDcEIsTUFBSSxNQUFNLE1BQU0sTUFBTSxjQUFjO0FBQ2xDLFdBQU87QUFBQSxFQUNUO0FBQ0EsUUFBTSxTQUFVLEtBQXVCO0FBQ3ZDLFNBQU8sT0FBTyxXQUFXLFdBQVcsT0FBTyxZQUFZLElBQUk7QUFDN0Q7QUFFQSxTQUFTLGVBQWUsTUFBMEM7QUFDaEUsUUFBTSxNQUFNLElBQUksSUFBSTtBQUNwQixNQUFJLE1BQU0sTUFBTSxNQUFNLGNBQWM7QUFDbEMsV0FBTztBQUFBLEVBQ1Q7QUFDQSxTQUFRLEtBQXVCO0FBQ2pDO0FBRUEsU0FBUyxlQUFlLE1BQW1DO0FBQ3pELFFBQU0sTUFBTSxJQUFJLElBQUk7QUFDcEIsTUFBSSxNQUFNLE1BQU0sTUFBTSx5QkFBeUIsTUFBTSxNQUFNLE1BQU0sVUFBVTtBQUN6RSxXQUFPO0FBQUEsRUFDVDtBQUNBLFNBQU8sT0FBTyxJQUFJLE9BQU8sTUFBTSxXQUFXLElBQUksT0FBTyxJQUFJO0FBQzNEO0FBRUEsU0FBUyxlQUFlLE1BQW1DO0FBQ3pELFFBQU0sTUFBTSxJQUFJLElBQUk7QUFDcEIsU0FBTyxNQUFNLE1BQU0sTUFBTSxZQUFZLE9BQU8sSUFBSSxPQUFPLE1BQU0sV0FBVyxJQUFJLE9BQU8sSUFBSTtBQUN6RjtBQU1BLFNBQVMsa0JBQWtCLE1BQXdDO0FBQ2pFLFFBQU0sS0FBSyxJQUFJLElBQUk7QUFDbkIsTUFBSSxLQUFLLE1BQU0sTUFBTSxZQUFZO0FBQy9CLFdBQU87QUFBQSxFQUNUO0FBQ0EsTUFBSSxnQkFBZ0IsSUFBSSxNQUFNLFNBQVM7QUFDckMsV0FBTztBQUFBLEVBQ1Q7QUFDQSxRQUFNLE9BQVEsR0FBRyxNQUFNLEdBQXlDO0FBQ2hFLE1BQUksQ0FBQyxNQUFNLFFBQVEsSUFBSSxLQUFLLEtBQUssU0FBUyxHQUFHO0FBQzNDLFdBQU87QUFBQSxFQUNUO0FBQ0EsTUFBSSxjQUFjLEtBQUssQ0FBQyxDQUFDLE1BQU0sT0FBTztBQUNwQyxXQUFPO0FBQUEsRUFDVDtBQUNBLE1BQUksZUFBZSxLQUFLLENBQUMsQ0FBQyxNQUFNLEtBQUs7QUFDbkMsV0FBTztBQUFBLEVBQ1Q7QUFDQSxTQUFPLE1BQU0sUUFBUSxHQUFHLGFBQWEsQ0FBQyxLQUFNLEdBQUcsYUFBYSxFQUFnQixTQUFTO0FBQ3ZGO0FBR0EsU0FBUyxzQkFBc0IsTUFBb0M7QUFDakUsUUFBTSxLQUFLLElBQUksSUFBSTtBQUNuQixNQUFJLEtBQUssTUFBTSxNQUFNLFlBQVk7QUFDL0IsV0FBTztBQUFBLEVBQ1Q7QUFDQSxNQUFJLGdCQUFnQixJQUFJLE1BQU0sZUFBZTtBQUMzQyxXQUFPO0FBQUEsRUFDVDtBQUNBLFFBQU0sWUFBYSxHQUFHLE1BQU0sR0FBeUM7QUFDckUsTUFBSSxDQUFDLE1BQU0sUUFBUSxTQUFTLEtBQUssVUFBVSxXQUFXLEdBQUc7QUFDdkQsV0FBTztBQUFBLEVBQ1Q7QUFDQSxRQUFNLFVBQVUsSUFBSSxVQUFVLENBQUMsQ0FBQztBQUNoQyxNQUFJLFVBQVUsTUFBTSxNQUFNLFlBQVk7QUFDcEMsV0FBTztBQUFBLEVBQ1Q7QUFDQSxNQUFJLGdCQUFnQixVQUFVLENBQUMsQ0FBQyxNQUFNLFNBQVM7QUFDN0MsV0FBTztBQUFBLEVBQ1Q7QUFDQSxRQUFNLFlBQWEsUUFBUSxNQUFNLEdBQXlDO0FBQzFFLE1BQUksQ0FBQyxNQUFNLFFBQVEsU0FBUyxLQUFLLFVBQVUsU0FBUyxHQUFHO0FBQ3JELFdBQU87QUFBQSxFQUNUO0FBQ0EsU0FBTyxjQUFjLFVBQVUsQ0FBQyxDQUFDLE1BQU0sU0FBUyxlQUFlLFVBQVUsQ0FBQyxDQUFDLE1BQU07QUFDbkY7QUFJQSxTQUFTLDJCQUEyQixNQUEwQztBQUM1RSxRQUFNLFVBQVUsY0FBYyxJQUFJO0FBQ2xDLE1BQUksWUFBWSxRQUFXO0FBQ3pCLFdBQU8sZUFBZSxJQUFJO0FBQUEsRUFDNUI7QUFFQSxNQUFJLGtCQUFrQixJQUFJLEdBQUc7QUFDM0IsVUFBTSxPQUFRLElBQUksSUFBSSxJQUFJLE1BQU0sR0FBeUM7QUFDekUsV0FBTyxlQUFlLE9BQU8sQ0FBQyxDQUFDLEtBQUs7QUFBQSxFQUN0QztBQUNBLE1BQUksc0JBQXNCLElBQUksR0FBRztBQUMvQixVQUFNLFlBQWEsSUFBSSxJQUFJLElBQUksTUFBTSxHQUF5QztBQUM5RSxVQUFNLFVBQVUsSUFBSSxZQUFZLENBQUMsQ0FBQztBQUNsQyxVQUFNLFlBQWEsVUFBVSxNQUFNLEdBQXlDO0FBQzVFLFdBQU8sZUFBZSxZQUFZLENBQUMsQ0FBQyxLQUFLO0FBQUEsRUFDM0M7QUFDQSxTQUFPO0FBQ1Q7QUFNQSxTQUFTLG1CQUFtQixNQUFjLFlBQTJEO0FBQ25HLE1BQUksS0FBSyxhQUFhLEtBQUs7QUFDekIsV0FBTztBQUFBLEVBQ1Q7QUFDQSxRQUFNLEVBQUUsTUFBTSxNQUFNLElBQUk7QUFFeEIsUUFBTSxpQkFBaUIsMkJBQTJCLElBQUk7QUFHdEQsTUFBSSxtQkFBbUIsUUFBUSxtQkFBbUIsVUFBYSxlQUFlLFFBQVEsbUJBQW1CLFlBQVk7QUFDbkgsV0FBTztBQUFBLEVBQ1Q7QUFHQSxNQUFJLGNBQWMsSUFBSSxNQUFNLFVBQVU7QUFDcEMsVUFBTSxRQUFRLGVBQWUsS0FBSztBQUNsQyxRQUFJLFVBQVUsUUFBVztBQUN2QixhQUFPLENBQUMsT0FBTyxXQUFXLFdBQVc7QUFBQSxJQUN2QztBQUFBLEVBQ0Y7QUFHQSxNQUFJLGNBQWMsSUFBSSxNQUFNLGtCQUFrQjtBQUM1QyxVQUFNLFFBQVEsZUFBZSxLQUFLO0FBQ2xDLFFBQUksVUFBVSxRQUFXO0FBQ3ZCLGFBQU8sQ0FBQyxPQUFPLFNBQVMsaUJBQWlCLGlCQUFpQjtBQUFBLElBQzVEO0FBQUEsRUFDRjtBQUdBLE1BQUksa0JBQWtCLElBQUksR0FBRztBQUMzQixVQUFNLFFBQVEsS0FBSyxZQUFZLENBQUMsR0FBRyxNQUFNO0FBQ3pDLFVBQU0sUUFBUSxlQUFlLEtBQUs7QUFDbEMsUUFBSSxPQUFPLFVBQVUsWUFBWSxVQUFVLFFBQVc7QUFDcEQsYUFBTyxDQUFDLFNBQVM7QUFDZixjQUFNLFFBQVEsS0FBSyxNQUFNLEdBQUc7QUFDNUIsY0FBTSxPQUFPLE1BQU0sUUFBUSxDQUFDO0FBQzVCLFlBQUksc0JBQXNCLEVBQUUsTUFBTSxPQUFPLE1BQU0sTUFBTSxDQUFDO0FBQ3RELGVBQU8sTUFBTSxXQUFXLEdBQUcsTUFBTSxPQUFPLE9BQU8sU0FBUztBQUFBLE1BQzFEO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFHQSxNQUFJLHNCQUFzQixJQUFJLEdBQUc7QUFDL0IsVUFBTSxRQUFRLGVBQWUsS0FBSztBQUNsQyxRQUFJLFVBQVUsUUFBVztBQUN2QixhQUFPLENBQUMsU0FBUyxLQUFLLE1BQU0sR0FBRyxFQUFFLFdBQVc7QUFBQSxJQUM5QztBQUFBLEVBQ0Y7QUFFQSxTQUFPO0FBQ1Q7QUFFQSxTQUFTLGVBQWUsTUFBZSxZQUErQztBQUNwRixRQUFNLE9BQU8sSUFBSSxJQUFJO0FBQ3JCLE1BQUksT0FBTyxNQUFNLE1BQU0sZUFBZTtBQUNwQyxXQUFPO0FBQUEsRUFDVDtBQUVBLFFBQU0sU0FBUztBQUVmLFVBQVEsT0FBTyxVQUFVO0FBQUEsSUFDdkIsS0FBSyxPQUFPO0FBQ1YsWUFBTSxXQUFXLGVBQWUsT0FBTyxNQUFNLFVBQVU7QUFDdkQsWUFBTSxZQUFZLGVBQWUsT0FBTyxPQUFPLFVBQVU7QUFDekQsYUFBTyxDQUFDLE1BQU0sUUFBUSxTQUFTLFNBQVMsTUFBTSxRQUFRLElBQUksS0FBSyxVQUFVLE1BQU0sUUFBUSxJQUFJO0FBQUEsSUFDN0Y7QUFBQSxJQUNBLEtBQUssTUFBTTtBQUNULFlBQU0sV0FBVyxlQUFlLE9BQU8sTUFBTSxVQUFVO0FBQ3ZELFlBQU0sWUFBWSxlQUFlLE9BQU8sT0FBTyxVQUFVO0FBQ3pELGFBQU8sQ0FBQyxNQUFNLFFBQVEsU0FBUyxTQUFTLE1BQU0sUUFBUSxJQUFJLEtBQUssVUFBVSxNQUFNLFFBQVEsSUFBSTtBQUFBLElBQzdGO0FBQUEsSUFDQSxLQUFLLE9BQU87QUFDVixZQUFNLFlBQVksZUFBZSxPQUFPLE1BQU0sVUFBVTtBQUN4RCxhQUFPLENBQUMsTUFBTSxRQUFRLFNBQVMsQ0FBQyxVQUFVLE1BQU0sUUFBUSxJQUFJO0FBQUEsSUFDOUQ7QUFBQSxJQUNBLFNBQVM7QUFDUCxhQUFPLG1CQUFtQixRQUFRLFVBQVUsS0FBSztBQUFBLElBQ25EO0FBQUEsRUFDRjtBQUNGO0FBRU8sU0FBUyxTQUNkLFdBQ0EsVUFDQSxZQUNnQztBQUNoQyxRQUFNLGFBQWMsU0FBb0MsTUFBTTtBQUM5RCxRQUFNLFlBQVksZUFBZ0IsVUFBa0MsU0FBUyxNQUFNLFVBQVU7QUFFN0YsUUFBTSxnQkFBb0MsV0FDdkMsUUFBUSxDQUFDLGNBQWMsT0FBTyxRQUFRLFVBQVUsSUFBSSxDQUFDLEVBQ3JEO0FBQUEsSUFBUSxDQUFDLENBQUMsTUFBTSxVQUFVLE1BQ3pCLE9BQU8sUUFBUSxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxnQkFBZ0IsT0FBTztBQUFBLE1BQzlEO0FBQUEsTUFDQSxRQUFRLE9BQU8sWUFBWTtBQUFBLE1BQzNCO0FBQUEsSUFDRixFQUFFO0FBQUEsRUFDSjtBQUNGLE1BQUksMkJBQTJCLGNBQWMsTUFBTTtBQUVuRCxRQUFNLGNBQWMsY0FBYztBQUFBLElBQVEsQ0FBQyxFQUFFLE1BQU0sUUFBUSxpQkFBaUIsTUFDMUUsT0FBTyxRQUFRLGlCQUFpQixTQUFTLEVBQUU7QUFBQSxNQUFRLENBQUMsQ0FBQyxjQUFjLGNBQWMsTUFDL0UsVUFBVSxNQUFNLFFBQVEsWUFBWSxJQUNoQyxDQUFDLEVBQUUsTUFBTSxRQUFRLFNBQVMsaUJBQWlCLFNBQVMsVUFBVSxlQUFlLENBQUMsSUFDOUUsQ0FBQztBQUFBLElBQ1A7QUFBQSxFQUNGO0FBQ0EsTUFBSSxnQkFBZ0IsWUFBWSxNQUFNO0FBRXRDLE1BQUksWUFBWSxXQUFXLEdBQUc7QUFDNUIsUUFBSSxnQkFBZ0I7QUFDcEIsVUFBTSxJQUFJLE1BQU0sZ0JBQWdCO0FBQUEsRUFDbEM7QUFDQSxTQUFPO0FBQ1Q7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -235,6 +235,21 @@ function checkSelect(selectAST, ctx, withTableName) {
235
235
  const columns = resolveSelectColumns(select, selectCtx);
236
236
  applyUnnestPost(deferredUnnest, columns);
237
237
  log("resolved columns", [...columns.keys()]);
238
+ const allTables = [...selectCtx.tables.values()].flat();
239
+ if (select.where !== null) {
240
+ validateComplexColumnExpression(select.where, allTables, selectCtx);
241
+ }
242
+ if (select.having !== null) {
243
+ validateComplexColumnExpression(select.having, allTables, selectCtx);
244
+ }
245
+ for (const orderItem of select.orderby ?? []) {
246
+ validateComplexColumnExpression(orderItem.expr, allTables, selectCtx);
247
+ }
248
+ if (select.groupby?.columns !== void 0) {
249
+ for (const groupCol of select.groupby.columns) {
250
+ validateComplexColumnExpression(groupCol, allTables, selectCtx);
251
+ }
252
+ }
238
253
  if (select._next !== void 0) {
239
254
  checkSelect(select._next, ctx, withTableName);
240
255
  }
@@ -328,4 +343,4 @@ export {
328
343
  athena_default as default,
329
344
  ruleId
330
345
  };
331
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hdGhlbmEudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBUUEsU0FBUyxVQUFVLGNBQWM7QUFFakMsT0FBTyxXQUFXO0FBQ2xCLFNBQVMsZ0JBQWdCO0FBQ3pCLFNBQVMsbUJBQWtDO0FBRzNDLFNBQVMsYUFBYTtBQUV0QixTQUFTLGdCQUFnQjtBQUN6QixTQUFTLGlCQUFpQjtBQUMxQjtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FJSztBQUNQLFNBQVMsMEJBQTBCO0FBQ25DO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBRUEsSUFBTSxTQUFTO0FBRXRCLElBQU0sTUFBTSxNQUFNLHNCQUFzQjtBQUN4QyxJQUFNLGFBQWEsWUFBWSxZQUFZLENBQUMsU0FBUyxJQUFJO0FBRXpELElBQU0sZ0JBQWdCO0FBQ3RCLElBQU0sZUFBZTtBQUVyQixJQUFNLGNBQU4sY0FBMEIsTUFBTTtBQUFBLEVBQ3ZCO0FBQUEsRUFDUCxZQUFZLE1BQWMsU0FBaUI7QUFDekMsVUFBTSxPQUFPO0FBQ2IsU0FBSyxPQUFPO0FBQ1osU0FBSyxPQUFPO0FBQUEsRUFDZDtBQUNGO0FBTUEsU0FBUyxZQUFZLE1BQWMsUUFBc0IsS0FBOEI7QUFDckYsU0FBTyxRQUFRLFNBQVksRUFBRSxNQUFNLFFBQVEsSUFBSSxJQUFJLEVBQUUsTUFBTSxPQUFPO0FBQ3BFO0FBR0EsU0FBUyxjQUFjLGFBQXFCLEtBQW1CO0FBQzdELE1BQUksVUFBVSxJQUFJLFdBQVcsSUFBSSxXQUFXO0FBQzVDLE1BQUksWUFBWSxRQUFXO0FBQ3pCLGNBQVUsVUFBVSxXQUFXO0FBQy9CLFFBQUksV0FBVyxJQUFJLGFBQWEsT0FBTztBQUFBLEVBQ3pDO0FBQ0EsU0FBTztBQUNUO0FBR0EsU0FBUyxhQUFhLGFBQXFCLEtBQW9DO0FBQzdFLFFBQU0sWUFBWSxJ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
346
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hdGhlbmEudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBUUEsU0FBUyxVQUFVLGNBQWM7QUFFakMsT0FBTyxXQUFXO0FBQ2xCLFNBQVMsZ0JBQWdCO0FBQ3pCLFNBQVMsbUJBQWtDO0FBRzNDLFNBQVMsYUFBYTtBQUV0QixTQUFTLGdCQUFnQjtBQUN6QixTQUFTLGlCQUFpQjtBQUMxQjtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FJSztBQUNQLFNBQVMsMEJBQTBCO0FBQ25DO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBRUEsSUFBTSxTQUFTO0FBRXRCLElBQU0sTUFBTSxNQUFNLHNCQUFzQjtBQUN4QyxJQUFNLGFBQWEsWUFBWSxZQUFZLENBQUMsU0FBUyxJQUFJO0FBRXpELElBQU0sZ0JBQWdCO0FBQ3RCLElBQU0sZUFBZTtBQUVyQixJQUFNLGNBQU4sY0FBMEIsTUFBTTtBQUFBLEVBQ3ZCO0FBQUEsRUFDUCxZQUFZLE1BQWMsU0FBaUI7QUFDekMsVUFBTSxPQUFPO0FBQ2IsU0FBSyxPQUFPO0FBQ1osU0FBSyxPQUFPO0FBQUEsRUFDZDtBQUNGO0FBTUEsU0FBUyxZQUFZLE1BQWMsUUFBc0IsS0FBOEI7QUFDckYsU0FBTyxRQUFRLFNBQVksRUFBRSxNQUFNLFFBQVEsSUFBSSxJQUFJLEVBQUUsTUFBTSxPQUFPO0FBQ3BFO0FBR0EsU0FBUyxjQUFjLGFBQXFCLEtBQW1CO0FBQzdELE1BQUksVUFBVSxJQUFJLFdBQVcsSUFBSSxXQUFXO0FBQzVDLE1BQUksWUFBWSxRQUFXO0FBQ3pCLGNBQVUsVUFBVSxXQUFXO0FBQy9CLFFBQUksV0FBVyxJQUFJLGFBQWEsT0FBTztBQUFBLEVBQ3pDO0FBQ0EsU0FBTztBQUNUO0FBR0EsU0FBUyxhQUFhLGFBQXFCLEtBQW9DO0FBQzdFLFFBQU0sWUFBWSxJ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QUFBQSxFQUNGO0FBQUEsRUFDQSxnQkFBZ0IsQ0FBQztBQUFBLEVBQ2pCLE9BQU8sU0FBUztBQUNkLGFBQVMsU0FBUyxLQUFhLFNBQXdCO0FBQ3JELFVBQUksQ0FBQyxxRUFBcUUsS0FBSyxHQUFHLEdBQUc7QUFDbkYsWUFBSSxrQ0FBa0MsRUFBRSxJQUFJLENBQUM7QUFDN0M7QUFBQSxNQUNGO0FBRUEsVUFBSTtBQUNKLFVBQUk7QUFFRixTQUFDLEVBQUUsSUFBSSxJQUFJLE1BQU0sS0FBSyxFQUFFLGtCQUFrQixLQUFLLENBQUM7QUFBQSxNQUNsRCxTQUFTLE9BQU87QUFDZCxZQUFJLDZCQUE2QixFQUFFLE9BQU8sSUFBSSxDQUFDO0FBQy9DLGdCQUFRLE9BQU87QUFBQSxVQUNiLE1BQU07QUFBQSxVQUNOLFdBQVc7QUFBQSxVQUNYLE1BQU0sRUFBRSxjQUFjLEtBQUssVUFBVSxPQUFPLFFBQVcsQ0FBQyxHQUFHLElBQUk7QUFBQSxRQUNqRSxDQUFDO0FBQ0Q7QUFBQSxNQUNGO0FBRUEsWUFBTSxZQUFZLGtCQUFrQjtBQUNwQyxVQUFJO0FBRUYsdUJBQWUsTUFBTSxRQUFRLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFNBQVM7QUFBQSxNQUM3RCxTQUFTLE9BQU87QUFDZCxZQUFJLDZCQUE2QixFQUFFLE9BQU8sSUFBSSxDQUFDO0FBQy9DLFlBQUksaUJBQWlCLGFBQWE7QUFDaEMsa0JBQVEsT0FBTztBQUFBLFlBQ2IsTUFBTTtBQUFBLFlBQ04sV0FBVztBQUFBLFlBQ1gsTUFBTSxFQUFFLGNBQWMsTUFBTSxRQUFRO0FBQUEsVUFDdEMsQ0FBQztBQUFBLFFBQ0gsT0FBTztBQUVMLGtCQUFRLE1BQU0sbUJBQW1CLE1BQU0sY0FBYyxRQUFRLFFBQVEsTUFBTSxLQUFLO0FBQ2hGLGtCQUFRLE9BQU87QUFBQSxZQUNiLE1BQU07QUFBQSxZQUNOLFdBQVc7QUFBQSxZQUNYLE1BQU07QUFBQSxjQUNKLGNBQWMsaUJBQWlCLFFBQVEsT0FBTyxLQUFLLElBQUksS0FBSyxVQUFVLE9BQU8sUUFBVyxDQUFDO0FBQUEsWUFDM0Y7QUFBQSxVQUNGLENBQUM7QUFBQSxRQUNIO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFFQSxXQUFPO0FBQUEsTUFDTCxnQkFBZ0IsU0FBUztBQUN2QixjQUFNLE1BQU0sUUFBUSxPQUNqQixJQUFJLENBQUMsVUFBVSxNQUFNLE1BQU0sTUFBTSxFQUNqQyxLQUFLLEVBQUUsRUFDUCxLQUFLO0FBQ1IsaUJBQVMsS0FBSyxPQUFPO0FBQUEsTUFDdkI7QUFBQSxNQUNBLFFBQVEsU0FBUztBQUNmLFlBQUksT0FBTyxRQUFRLFVBQVUsVUFBVTtBQUNyQztBQUFBLFFBQ0Y7QUFDQSxpQkFBUyxRQUFRLE9BQU8sT0FBTztBQUFBLE1BQ2pDO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRixDQUFDO0FBRUQsSUFBTyxpQkFBUTsiLAogICJuYW1lcyI6IFsidGFibGVOYW1lIiwgImFsaWFzIiwgImFwaVNjaGVtYXMiLCAib3BlcmF0aW9ucyJdCn0K
@@ -230,9 +230,9 @@ export interface Select {
230
230
  from: From[] | TableExpr | null;
231
231
  where: Binary | Function | null;
232
232
  groupby: {
233
- columns: ColumnRef[] | null;
233
+ columns: ColumnRef[] | undefined;
234
234
  modifiers: ValueExpr<string>[];
235
- };
235
+ } | undefined;
236
236
  having: any[] | null;
237
237
  orderby: OrderBy[] | null;
238
238
  limit: Limit | null;
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@checkdigit/eslint-plugin","version":"7.18.0-PR.143-8290","description":"Check Digit eslint plugins","keywords":["eslint","eslintplugin"],"homepage":"https://github.com/checkdigit/eslint-plugin#readme","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"repository":{"type":"git","url":"https://github.com/checkdigit/eslint-plugin"},"license":"MIT","author":"Check Digit, LLC","sideEffects":false,"type":"module","exports":{".":{"types":"./dist-types/index.d.ts","import":"./dist-mjs/index.mjs","default":"./dist-mjs/index.mjs"}},"files":["src","dist-types","dist-mjs","!src/**/test/**","!src/**/*.test.ts","!src/**/*.spec.ts","!dist-types/**/test/**","!dist-types/**/*.test.d.ts","!dist-types/**/*.spec.d.ts","!dist-mjs/**/test/**","!dist-mjs/**/*.test.mjs","!dist-mjs/**/*.spec.mjs","SECURITY.md"],"scripts":{"build:dist-mjs":"rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs","build:dist-types":"rimraf dist-types && npx builder --type=types --outDir=dist-types","ci:compile":"tsc --noEmit","ci:coverage":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier","ci:test":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=false","lint":"eslint --max-warnings 0 .","lint:fix":"eslint --max-warnings 0 --fix .","peggy":"for file in ./src/peggy/*.peggy; do peggy \"$file\" --format es --output \"${file%.peggy}-peggy.ts\"; done","peggy-watch":"for file in ./src/peggy/*.peggy; do peggy \"$file\" --format=es --watch --output=\"${file%.peggy}-peggy.ts\"; done","prepare":"","prepublishOnly":"npm run build:dist-types && npm run build:dist-mjs","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style"},"prettier":"@checkdigit/prettier-config","jest":{"preset":"@checkdigit/jest-config"},"dependencies":{"@apidevtools/json-schema-ref-parser":"^15.3.5","@typescript-eslint/type-utils":"^8.60.1","@typescript-eslint/utils":"^8.60.1","ajv":"^8.20.0","debug":"^4.4.3","glob":"^13.0.6","http-status-codes":"^2.3.0","js-yaml":"^4.2.0","json-pointer":"^0.6.2","jsonpath-plus":"^10.4.0","ts-api-utils":"^2.5.0"},"devDependencies":{"@checkdigit/jest-config":"^6.0.2","@checkdigit/prettier-config":"^6.1.0","@checkdigit/typescript-config":"10.0.0","@eslint/js":"^9.37.0","@types/debug":"^4.1.13","@types/eslint":"^9.6.1","@types/eslint-config-prettier":"^6.11.3","@types/js-yaml":"^4.0.9","@types/json-pointer":"^1.0.34","@typescript-eslint/parser":"^8.60.1","@typescript-eslint/rule-tester":"^8.60.1","eslint":"^9.37.0","eslint-config-prettier":"^10.1.8","eslint-import-resolver-typescript":"^4.4.5","eslint-plugin-eslint-plugin":"^6.4.0","eslint-plugin-import":"^2.32.0","eslint-plugin-no-only-tests":"^3.4.0","eslint-plugin-no-secrets":"^2.3.3","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"^1.0.4","openapi-types":"^12.1.3","peggy":"^4.2.0","rimraf":"^6.1.3","typescript-eslint":"^8.60.1"},"peerDependencies":{"eslint":">=9 <10"},"engines":{"node":">=22.18"},"service":{"api":{"root":"src","endpoints":["api/v1"]}},"wallaby":{"env":{"params":{"runner":"--experimental-vm-modules"}}}}
1
+ {"name":"@checkdigit/eslint-plugin","version":"7.18.0-PR.143-0de2","description":"Check Digit eslint plugins","keywords":["eslint","eslintplugin"],"homepage":"https://github.com/checkdigit/eslint-plugin#readme","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"repository":{"type":"git","url":"https://github.com/checkdigit/eslint-plugin"},"license":"MIT","author":"Check Digit, LLC","sideEffects":false,"type":"module","exports":{".":{"types":"./dist-types/index.d.ts","import":"./dist-mjs/index.mjs","default":"./dist-mjs/index.mjs"}},"files":["src","dist-types","dist-mjs","!src/**/test/**","!src/**/*.test.ts","!src/**/*.spec.ts","!dist-types/**/test/**","!dist-types/**/*.test.d.ts","!dist-types/**/*.spec.d.ts","!dist-mjs/**/test/**","!dist-mjs/**/*.test.mjs","!dist-mjs/**/*.spec.mjs","SECURITY.md"],"scripts":{"build:dist-mjs":"rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs","build:dist-types":"rimraf dist-types && npx builder --type=types --outDir=dist-types","ci:compile":"tsc --noEmit","ci:coverage":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier","ci:test":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=false","lint":"eslint --max-warnings 0 .","lint:fix":"eslint --max-warnings 0 --fix .","peggy":"for file in ./src/peggy/*.peggy; do peggy \"$file\" --format es --output \"${file%.peggy}-peggy.ts\"; done","peggy-watch":"for file in ./src/peggy/*.peggy; do peggy \"$file\" --format=es --watch --output=\"${file%.peggy}-peggy.ts\"; done","prepare":"","prepublishOnly":"npm run build:dist-types && npm run build:dist-mjs","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style"},"prettier":"@checkdigit/prettier-config","jest":{"preset":"@checkdigit/jest-config"},"dependencies":{"@apidevtools/json-schema-ref-parser":"^15.3.5","@typescript-eslint/type-utils":"^8.60.1","@typescript-eslint/utils":"^8.60.1","ajv":"^8.20.0","debug":"^4.4.3","glob":"^13.0.6","http-status-codes":"^2.3.0","js-yaml":"^4.2.0","json-pointer":"^0.6.2","jsonpath-plus":"^10.4.0","ts-api-utils":"^2.5.0"},"devDependencies":{"@checkdigit/jest-config":"^6.0.2","@checkdigit/prettier-config":"^6.1.0","@checkdigit/typescript-config":"10.0.0","@eslint/js":"^9.37.0","@types/debug":"^4.1.13","@types/eslint":"^9.6.1","@types/eslint-config-prettier":"^6.11.3","@types/js-yaml":"^4.0.9","@types/json-pointer":"^1.0.34","@typescript-eslint/parser":"^8.60.1","@typescript-eslint/rule-tester":"^8.60.1","eslint":"^9.37.0","eslint-config-prettier":"^10.1.8","eslint-import-resolver-typescript":"^4.4.5","eslint-plugin-eslint-plugin":"^6.4.0","eslint-plugin-import":"^2.32.0","eslint-plugin-no-only-tests":"^3.4.0","eslint-plugin-no-secrets":"^2.3.3","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"^1.0.4","openapi-types":"^12.1.3","peggy":"^4.2.0","rimraf":"^6.1.3","typescript-eslint":"^8.60.1"},"peerDependencies":{"eslint":">=9 <10"},"engines":{"node":">=22.18"},"service":{"api":{"root":"src","endpoints":["api/v1"]}},"wallaby":{"env":{"params":{"runner":"--experimental-vm-modules"}}}}
@@ -1,10 +1,10 @@
1
1
  // athena/api-matcher.ts
2
2
 
3
3
  import debug from 'debug';
4
- import { JSONPath } from 'jsonpath-plus';
5
4
  import type { SchemaObject } from 'ajv/dist/2020';
6
5
 
7
6
  import type { ApiSchemas, OperationSchemas } from '../openapi/generate-schema';
7
+ import type { Binary, ColumnRefItem, Function as SqlFunction } from './types';
8
8
 
9
9
  const log = debug('eslint-plugin:athena:api-matcher');
10
10
 
@@ -21,105 +21,226 @@ export interface MatchedOperation {
21
21
  response: SchemaObject;
22
22
  }
23
23
 
24
- type Matcher = (path: string, method: string) => boolean;
24
+ // A predicate over an API operation candidate: (url path, HTTP method, HTTP response code)
25
+ type OperationPredicate = (path: string, method: string, responseCode: string) => boolean;
25
26
 
26
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
27
- function getVersionMatcher(_selectAST: object, _tableAST: object): Matcher | undefined {
28
- return undefined;
27
+ const ALWAYS_TRUE: OperationPredicate = () => true;
28
+
29
+ // --- AST accessor helpers (use Record<string,unknown> to avoid TypeScript narrowing conflicts) ---
30
+
31
+ function rec(node: unknown): Record<string, unknown> | undefined {
32
+ return typeof node === 'object' && node !== null ? (node as Record<string, unknown>) : undefined;
29
33
  }
30
34
 
31
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
32
- function getPathPartMatcher(selectAST: object, _tableAST: object): Matcher | undefined {
33
- const [pathPartCondition]: object[] = JSONPath({
34
- json: selectAST,
35
- path: "$.where..[?(@ && @.type === 'binary_expr' && @.operator === '=' && @.left && @.left.type === 'function' && @.left.name && @.left.name.name && @.left.name.name[0] && @.left.name.name[0].value === 'split' && @.left.args && @.left.args.value && @.left.args.value[0] && @.left.args.value[0].type === 'column_ref' && @.left.args.value[0].column === 'url' && @.left.args.value[1] && @.left.args.value[1].type === 'single_quote_string' && @.left.args.value[1].value === '/' && @.left.array_index && @.left.array_index[0] && @.left.array_index[0].brackets === true && @.left.array_index[0].index && @.left.array_index[0].index.type === 'number')]",
36
- }); /*?*/
37
- // log('pathPartCondition', pathPartCondition);
38
-
39
- if (pathPartCondition !== undefined) {
40
- const [pathPartIndex]: [number] = JSONPath({
41
- json: pathPartCondition,
42
- path: '$.left.array_index[0].index.value',
43
- }); /*?*/
44
- const [pathPartMatch]: [string] = JSONPath({
45
- json: pathPartCondition,
46
- path: '$.right.value',
47
- }); /*?*/
48
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
49
- return (path: string, _method: string) => {
50
- const parts = path.split('/'); /*?*/
51
- const part = parts[pathPartIndex - 1]; //athena index is larger than js index by one /*?*/
52
- log(`checking path part`, { path, pathPartIndex, part, pathPartMatch });
53
- return part?.startsWith(':') === true
54
- ? true // ignore path part if it presents a dynamic input parameter
55
- : parts[pathPartIndex - 1] === pathPartMatch; // try to match with static path part
56
- };
35
+ function getFunctionName(node: unknown): string | undefined {
36
+ const fn = rec(node);
37
+ if (fn?.['type'] !== 'function') {
38
+ return undefined;
57
39
  }
40
+ const name = fn['name'] as SqlFunction['name'] | undefined;
41
+ const firstName = name?.name[0];
42
+ return firstName === undefined ? undefined : firstName.value.toLowerCase();
43
+ }
58
44
 
59
- return undefined;
45
+ function getColumnName(node: unknown): string | undefined {
46
+ const col = rec(node);
47
+ if (col?.['type'] !== 'column_ref') {
48
+ return undefined;
49
+ }
50
+ const column = (node as ColumnRefItem).column;
51
+ return typeof column === 'string' ? column.toLowerCase() : undefined;
60
52
  }
61
53
 
62
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
- function getPathPartsCountMatcher(selectAST: object, _tableAST: object): Matcher | undefined {
64
- // log('getPathPartsCountMatcher', JSON.stringify(selectAST, undefined, 2));
65
- const [pathPartCount]: number[] = JSONPath({
66
- json: selectAST,
67
- path: "$.where..[?(@ && @.type === 'binary_expr' && @.operator === '=' && @.left && @.left.type === 'function' && @.left.name && @.left.name.name && @.left.name.name[0] && @.left.name.name[0].value === 'cardinality' && @.right && @.right.type === 'number' && @.left.args && @.left.args.value && @.left.args.value[0] && @.left.args.value[0].type === 'function' && @.left.args.value[0].name && @.left.args.value[0].name.name && @.left.args.value[0].name.name[0] && @.left.args.value[0].name.name[0].value === 'split' && @.left.args.value[0].args && @.left.args.value[0].args.value && @.left.args.value[0].args.value[0] && @.left.args.value[0].args.value[0].type === 'column_ref' && @.left.args.value[0].args.value[0].column === 'url' && @.left.args.value[0].args.value[1] && @.left.args.value[0].args.value[1].type === 'single_quote_string' && @.left.args.value[0].args.value[1].value === '/')].right.value",
68
- }); /*?*/
54
+ function getColumnTable(node: unknown): string | null | undefined {
55
+ const col = rec(node);
56
+ if (col?.['type'] !== 'column_ref') {
57
+ return undefined;
58
+ }
59
+ return (node as ColumnRefItem).table;
60
+ }
69
61
 
70
- if (pathPartCount !== undefined) {
71
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
72
- return (path: string, _method: string) => {
73
- const parts = path.split('/');
74
- return parts.length === pathPartCount;
75
- };
62
+ function getStringValue(node: unknown): string | undefined {
63
+ const val = rec(node);
64
+ if (val?.['type'] !== 'single_quote_string' && val?.['type'] !== 'string') {
65
+ return undefined;
76
66
  }
67
+ return typeof val['value'] === 'string' ? val['value'] : undefined;
68
+ }
77
69
 
78
- return undefined;
70
+ function getNumberValue(node: unknown): number | undefined {
71
+ const val = rec(node);
72
+ return val?.['type'] === 'number' && typeof val['value'] === 'number' ? val['value'] : undefined;
79
73
  }
80
74
 
81
- function getPathMatchers(selectAST: object, tableAST: object) {
82
- return [getPathPartMatcher(selectAST, tableAST), getPathPartsCountMatcher(selectAST, tableAST)];
75
+ // Matches: split(url, '/')[N] — a Function node carrying an array_index extension
76
+ interface SplitUrlIndexed extends SqlFunction {
77
+ array_index: { brackets: true; index: { type: string; value: unknown } }[];
78
+ }
79
+ function isSplitUrlIndexed(node: unknown): node is SplitUrlIndexed {
80
+ const fn = rec(node);
81
+ if (fn?.['type'] !== 'function') {
82
+ return false;
83
+ }
84
+ if (getFunctionName(node) !== 'split') {
85
+ return false;
86
+ }
87
+ const args = (fn['args'] as { value?: unknown[] } | undefined)?.value;
88
+ if (!Array.isArray(args) || args.length < 2) {
89
+ return false;
90
+ }
91
+ if (getColumnName(args[0]) !== 'url') {
92
+ return false;
93
+ }
94
+ if (getStringValue(args[1]) !== '/') {
95
+ return false;
96
+ }
97
+ return Array.isArray(fn['array_index']) && (fn['array_index'] as unknown[]).length > 0;
83
98
  }
84
99
 
85
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
86
- function getMethodMatcher(selectAST: object, _tableAST: object): Matcher | undefined {
87
- const [methodToMatch]: string[] = JSONPath({
88
- json: selectAST,
89
- path: "$.where..[?(@ && @.type === 'binary_expr' && @.operator === '=' && @.left && @.left.type === 'column_ref' && @.left.column === 'method' && @.right && @.right.type === 'single_quote_string')].right.value",
90
- }); /*?*/
100
+ // Matches: cardinality(split(url, '/'))
101
+ function isCardinalitySplitUrl(node: unknown): node is SqlFunction {
102
+ const fn = rec(node);
103
+ if (fn?.['type'] !== 'function') {
104
+ return false;
105
+ }
106
+ if (getFunctionName(node) !== 'cardinality') {
107
+ return false;
108
+ }
109
+ const outerArgs = (fn['args'] as { value?: unknown[] } | undefined)?.value;
110
+ if (!Array.isArray(outerArgs) || outerArgs.length === 0) {
111
+ return false;
112
+ }
113
+ const innerFn = rec(outerArgs[0]);
114
+ if (innerFn?.['type'] !== 'function') {
115
+ return false;
116
+ }
117
+ if (getFunctionName(outerArgs[0]) !== 'split') {
118
+ return false;
119
+ }
120
+ const innerArgs = (innerFn['args'] as { value?: unknown[] } | undefined)?.value;
121
+ if (!Array.isArray(innerArgs) || innerArgs.length < 2) {
122
+ return false;
123
+ }
124
+ return getColumnName(innerArgs[0]) === 'url' && getStringValue(innerArgs[1]) === '/';
125
+ }
91
126
 
92
- if (methodToMatch !== undefined) {
93
- return (_path: string, method: string) => method === methodToMatch;
127
+ // Returns the table qualifier of the left-hand side of a matchable binary condition.
128
+ // null means unqualified (applies to every table); undefined means indeterminate.
129
+ function getConditionTableQualifier(left: unknown): string | null | undefined {
130
+ const colName = getColumnName(left);
131
+ if (colName !== undefined) {
132
+ return getColumnTable(left);
133
+ }
134
+
135
+ if (isSplitUrlIndexed(left)) {
136
+ const args = (rec(left)?.['args'] as { value?: unknown[] } | undefined)?.value;
137
+ return getColumnTable(args?.[0]) ?? null;
138
+ }
139
+ if (isCardinalitySplitUrl(left)) {
140
+ const outerArgs = (rec(left)?.['args'] as { value?: unknown[] } | undefined)?.value;
141
+ const splitFn = rec(outerArgs?.[0]);
142
+ const innerArgs = (splitFn?.['args'] as { value?: unknown[] } | undefined)?.value;
143
+ return getColumnTable(innerArgs?.[0]) ?? null;
94
144
  }
95
145
  return undefined;
96
146
  }
97
147
 
98
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
99
- function getResponseStatusToMatch(selectAST: object, _tableAST: object): string | undefined {
100
- const [responseStatus]: string[] = JSONPath({
101
- json: selectAST,
102
- path: "$.where..[?(@ && @.type === 'binary_expr' && @.operator === '=' && @.left && @.left.type === 'column_ref' && @.left.column === 'responsestatus' && @.right && @.right.type === 'single_quote_string')].right.value",
103
- }); /*?*/
148
+ // --- Predicate builders ---
149
+
150
+ // tableAlias: the alias (or null if none) of the FROM-clause item we are currently matching.
151
+ // Conditions that explicitly reference a different alias are skipped (treated as ALWAYS_TRUE).
152
+ function buildLeafPredicate(node: Binary, tableAlias: string | null): OperationPredicate | undefined {
153
+ if (node.operator !== '=') {
154
+ return undefined;
155
+ }
156
+ const { left, right } = node;
157
+
158
+ const conditionTable = getConditionTableQualifier(left);
159
+ // conditionTable === null → unqualified, applies to all tables
160
+ // conditionTable === string → qualified; skip if it names a different alias
161
+ if (conditionTable !== null && conditionTable !== undefined && tableAlias !== null && conditionTable !== tableAlias) {
162
+ return undefined;
163
+ }
164
+
165
+ // method = 'GET'
166
+ if (getColumnName(left) === 'method') {
167
+ const value = getStringValue(right);
168
+ if (value !== undefined) {
169
+ return (_path, method) => method === value;
170
+ }
171
+ }
172
+
173
+ // responsestatus = '200'
174
+ if (getColumnName(left) === 'responsestatus') {
175
+ const value = getStringValue(right);
176
+ if (value !== undefined) {
177
+ return (_path, _method, responseCode) => responseCode === value;
178
+ }
179
+ }
180
+
181
+ // split(url, '/')[N] = 'value'
182
+ if (isSplitUrlIndexed(left)) {
183
+ const index = left.array_index[0]?.index.value;
184
+ const value = getStringValue(right);
185
+ if (typeof index === 'number' && value !== undefined) {
186
+ return (path) => {
187
+ const parts = path.split('/');
188
+ const part = parts[index - 1]; // athena index is 1-based
189
+ log(`checking path part`, { path, index, part, value });
190
+ return part?.startsWith(':') === true ? true : part === value;
191
+ };
192
+ }
193
+ }
104
194
 
105
- return responseStatus;
195
+ // cardinality(split(url, '/')) = N
196
+ if (isCardinalitySplitUrl(left)) {
197
+ const count = getNumberValue(right);
198
+ if (count !== undefined) {
199
+ return (path) => path.split('/').length === count;
200
+ }
201
+ }
202
+
203
+ return undefined;
204
+ }
205
+
206
+ function buildPredicate(expr: unknown, tableAlias: string | null): OperationPredicate {
207
+ const node = rec(expr);
208
+ if (node?.['type'] !== 'binary_expr') {
209
+ return ALWAYS_TRUE;
210
+ }
211
+
212
+ const binary = expr as Binary;
213
+
214
+ switch (binary.operator) {
215
+ case 'AND': {
216
+ const leftPred = buildPredicate(binary.left, tableAlias);
217
+ const rightPred = buildPredicate(binary.right, tableAlias);
218
+ return (path, method, code) => leftPred(path, method, code) && rightPred(path, method, code);
219
+ }
220
+ case 'OR': {
221
+ const leftPred = buildPredicate(binary.left, tableAlias);
222
+ const rightPred = buildPredicate(binary.right, tableAlias);
223
+ return (path, method, code) => leftPred(path, method, code) || rightPred(path, method, code);
224
+ }
225
+ case 'NOT': {
226
+ const innerPred = buildPredicate(binary.left, tableAlias);
227
+ return (path, method, code) => !innerPred(path, method, code);
228
+ }
229
+ default: {
230
+ return buildLeafPredicate(binary, tableAlias) ?? ALWAYS_TRUE;
231
+ }
232
+ }
106
233
  }
107
234
 
108
- // [TODO:] match only relevent table in case multiple tables are joined
109
235
  export function matchApi(
110
236
  selectAST: object,
111
237
  tableAST: object,
112
238
  apiSchemas: ApiSchemas[],
113
239
  ): MatchedOperation[] | undefined {
114
- const schemaMatchers: Matcher[] = [
115
- getVersionMatcher(selectAST, tableAST),
116
- getPathMatchers(selectAST, tableAST),
117
- getMethodMatcher(selectAST, tableAST),
118
- ]
119
- .flat()
120
- .filter<Matcher>((matcher) => matcher !== undefined);
121
-
122
- const allOperationSchemas: OperationToMatch[] = apiSchemas
240
+ const tableAlias = (tableAST as { as?: string | null }).as ?? null;
241
+ const predicate = buildPredicate((selectAST as { where?: unknown }).where ?? null, tableAlias);
242
+
243
+ const allOperations: OperationToMatch[] = apiSchemas
123
244
  .flatMap((apiSchema) => Object.entries(apiSchema.apis))
124
245
  .flatMap(([path, operations]) =>
125
246
  Object.entries(operations).map(([method, operationSchemas]) => ({
@@ -128,41 +249,19 @@ export function matchApi(
128
249
  operationSchemas,
129
250
  })),
130
251
  );
131
- log('total operation schemas', allOperationSchemas.length);
252
+ log('total operation schemas', allOperations.length);
132
253
 
133
- const matchedOperationSchemas = allOperationSchemas.filter(({ path, method }) =>
134
- schemaMatchers.every((matcher) => matcher(path, method)),
254
+ const matchedApis = allOperations.flatMap(({ path, method, operationSchemas }) =>
255
+ Object.entries(operationSchemas.responses).flatMap(([responseCode, responseSchema]) =>
256
+ predicate(path, method, responseCode)
257
+ ? [{ path, method, request: operationSchemas.request, response: responseSchema }]
258
+ : [],
259
+ ),
135
260
  );
136
- log('matched operation schemas', matchedOperationSchemas.length);
137
-
138
- if (matchedOperationSchemas.length === 0) {
139
- log('no matched operation schema');
140
- throw new Error('no matched operation schema');
141
- }
142
-
143
- const matchedResponseStatus = getResponseStatusToMatch(selectAST, tableAST);
144
- // [TODO:] should we allow multiple response status?
145
- // assert.ok(matchedResponseStatus !== undefined);
146
- log('matchedResponseStatus', matchedResponseStatus);
147
-
148
- const matchedApis = matchedOperationSchemas
149
- .flatMap((operation) =>
150
- Object.entries(operation.operationSchemas.responses).map(([responseCode, responseSchema]) => {
151
- const matchedResponseSchema =
152
- matchedResponseStatus === undefined || responseCode === matchedResponseStatus ? responseSchema : undefined;
153
- return matchedResponseSchema === undefined
154
- ? undefined
155
- : {
156
- path: operation.path,
157
- method: operation.method,
158
- request: operation.operationSchemas.request,
159
- response: matchedResponseSchema,
160
- };
161
- }),
162
- )
163
- .filter((api) => api !== undefined);
261
+ log('matched apis', matchedApis.length);
262
+
164
263
  if (matchedApis.length === 0) {
165
- log('no api satisfy both request and response matchers');
264
+ log('no matched api');
166
265
  throw new Error('no matched api');
167
266
  }
168
267
  return matchedApis;
@@ -379,6 +379,23 @@ function checkSelect(selectAST: Select | With, ctx: VisitContext, withTableName?
379
379
 
380
380
  log('resolved columns', [...columns.keys()]);
381
381
 
382
+ // Pass 3: validate JSON paths in WHERE / HAVING / GROUP BY / ORDER BY
383
+ const allTables = [...selectCtx.tables.values()].flat();
384
+ if (select.where !== null) {
385
+ validateComplexColumnExpression(select.where, allTables, selectCtx);
386
+ }
387
+ if (select.having !== null) {
388
+ validateComplexColumnExpression(select.having, allTables, selectCtx);
389
+ }
390
+ for (const orderItem of select.orderby ?? []) {
391
+ validateComplexColumnExpression(orderItem.expr, allTables, selectCtx);
392
+ }
393
+ if (select.groupby?.columns !== undefined) {
394
+ for (const groupCol of select.groupby.columns) {
395
+ validateComplexColumnExpression(groupCol, allTables, selectCtx);
396
+ }
397
+ }
398
+
382
399
  // UNION ALL — next SELECT in the chain
383
400
  if (select._next !== undefined) {
384
401
  checkSelect(select._next, ctx, withTableName);
@@ -268,7 +268,7 @@ export interface Select {
268
268
  columns: any[] | Column[];
269
269
  from: From[] | TableExpr | null;
270
270
  where: Binary | Function | null;
271
- groupby: { columns: ColumnRef[] | null; modifiers: ValueExpr<string>[] };
271
+ groupby: { columns: ColumnRef[] | undefined; modifiers: ValueExpr<string>[] } | undefined;
272
272
  having: any[] | null;
273
273
  orderby: OrderBy[] | null;
274
274
  limit: Limit | null;