@checkdigit/eslint-plugin 7.18.0-PR.143-b47c → 7.18.0-PR.143-cf9d
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-mjs/athena/api-locator.mjs +6 -9
- package/dist-mjs/athena/api-matcher.mjs +37 -77
- package/dist-mjs/athena/validate.mjs +130 -161
- package/dist-mjs/athena/visitor.mjs +32 -52
- package/dist-mjs/openapi/generate-schema.mjs +17 -23
- package/dist-mjs/openapi/service-schema-generator.mjs +7 -9
- package/dist-types/athena/visitor.d.ts +5 -3
- package/package.json +1 -1
- package/src/athena/api-locator.ts +5 -11
- package/src/athena/api-matcher.ts +45 -79
- package/src/athena/validate.ts +175 -170
- package/src/athena/visitor.ts +38 -71
- package/src/openapi/generate-schema.ts +18 -34
- package/src/openapi/service-schema-generator.ts +7 -8
|
@@ -6,9 +6,6 @@ var log = debug("eslint-plugin:athena:api-locator");
|
|
|
6
6
|
var SERVICES_ROOT_FOLDER = "src/services";
|
|
7
7
|
var LEGACY_TABLE_SUFFIX = "_logs";
|
|
8
8
|
var SCHEMA_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
9
|
-
function upperCaseFirstCharacter(value) {
|
|
10
|
-
return `${value[0]?.toUpperCase()}${value.slice(1)}`;
|
|
11
|
-
}
|
|
12
9
|
function locateApi(originalServiceName) {
|
|
13
10
|
log("locating API for service", originalServiceName);
|
|
14
11
|
let serviceName = originalServiceName;
|
|
@@ -16,12 +13,12 @@ function locateApi(originalServiceName) {
|
|
|
16
13
|
log('service table is a legacy table name, looking for API schemas after removing "_logs" suffix', serviceName);
|
|
17
14
|
serviceName = serviceName.slice(0, -LEGACY_TABLE_SUFFIX.length);
|
|
18
15
|
}
|
|
19
|
-
const
|
|
20
|
-
const camelCaseServiceName = [serviceNameParts[0], ...serviceNameParts.slice(1).map(upperCaseFirstCharacter)].join(
|
|
21
|
-
""
|
|
22
|
-
);
|
|
16
|
+
const camelCaseServiceName = serviceName.replace(/-(?<letter>[a-z])/gu, (_, letter) => letter.toUpperCase());
|
|
23
17
|
const allSchemaFilenames = fs.globSync(`${SERVICES_ROOT_FOLDER}/${camelCaseServiceName}/*/swagger.schema.deref.json`);
|
|
24
|
-
log(
|
|
18
|
+
log(
|
|
19
|
+
`${allSchemaFilenames.length.toString()} versions of API schemas located for service ${serviceName}`,
|
|
20
|
+
allSchemaFilenames
|
|
21
|
+
);
|
|
25
22
|
const outputDir = `${SERVICES_ROOT_FOLDER}/${camelCaseServiceName}`;
|
|
26
23
|
if (allSchemaFilenames.length > 0) {
|
|
27
24
|
const hasStaleSchema = allSchemaFilenames.some(
|
|
@@ -45,4 +42,4 @@ function locateApi(originalServiceName) {
|
|
|
45
42
|
export {
|
|
46
43
|
locateApi
|
|
47
44
|
};
|
|
48
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
45
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hcGktbG9jYXRvci50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFFQSxPQUFPLFFBQVE7QUFFZixPQUFPLFdBQVc7QUFFbEIsU0FBMEIsaUNBQWlDO0FBRTNELElBQU0sTUFBTSxNQUFNLGtDQUFrQztBQUVwRCxJQUFNLHVCQUF1QjtBQUM3QixJQUFNLHNCQUFzQjtBQUU1QixJQUFNLG9CQUFvQixLQUFLLEtBQUs7QUFFN0IsU0FBUyxVQUFVLHFCQUEyQztBQUNuRSxNQUFJLDRCQUE0QixtQkFBbUI7QUFFbkQsTUFBSSxjQUFjO0FBQ2xCLE1BQUksWUFBWSxTQUFTLG1CQUFtQixHQUFHO0FBQzdDLFFBQUksK0ZBQStGLFdBQVc7QUFDOUcsa0JBQWMsWUFBWSxNQUFNLEdBQUcsQ0FBQyxvQkFBb0IsTUFBTTtBQUFBLEVBQ2hFO0FBRUEsUUFBTSx1QkFBdUIsWUFBWSxRQUFRLHVCQUF1QixDQUFDLEdBQUcsV0FBbUIsT0FBTyxZQUFZLENBQUM7QUFFbkgsUUFBTSxxQkFBcUIsR0FBRyxTQUFTLEdBQUcsb0JBQW9CLElBQUksb0JBQW9CLDhCQUE4QjtBQUNwSDtBQUFBLElBQ0UsR0FBRyxtQkFBbUIsT0FBTyxTQUFTLENBQUMsZ0RBQWdELFdBQVc7QUFBQSxJQUNsRztBQUFBLEVBQ0Y7QUFFQSxRQUFNLFlBQVksR0FBRyxvQkFBb0IsSUFBSSxvQkFBb0I7QUFFakUsTUFBSSxtQkFBbUIsU0FBUyxHQUFHO0FBQ2pDLFVBQU0saUJBQWlCLG1CQUFtQjtBQUFBLE1BQ3hDLENBQUMsbUJBQW1CLEtBQUssSUFBSSxJQUFJLEdBQUcsU0FBUyxjQUFjLEVBQUUsVUFBVTtBQUFBLElBQ3pFO0FBQ0EsUUFBSSxnQkFBZ0I7QUFDbEIsVUFBSSw0RUFBNEUsV0FBVztBQUMzRixZQUFNLGNBQWMsMEJBQTBCLGFBQWEsU0FBUztBQUNwRSxVQUFJLFlBQVksU0FBUyxHQUFHO0FBQzFCLGVBQU8sWUFBWSxJQUFJLENBQUMsRUFBRSxPQUFPLE1BQU0sTUFBTTtBQUFBLE1BQy9DO0FBQ0EsVUFBSSx5RUFBeUUsV0FBVztBQUFBLElBQzFGO0FBQ0EsV0FBTyxtQkFBbUI7QUFBQSxNQUN4QixDQUFDLG1CQUFtQixLQUFLLE1BQU0sR0FBRyxhQUFhLGdCQUFnQixPQUFPLENBQUM7QUFBQSxJQUN6RTtBQUFBLEVBQ0Y7QUFFQSxNQUFJLCtFQUErRSxXQUFXO0FBQzlGLFNBQU8sMEJBQTBCLGFBQWEsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUFFLE9BQU8sTUFBTSxNQUFNO0FBQ3JGOyIsCiAgIm5hbWVzIjogW10KfQo=
|
|
@@ -14,20 +14,16 @@ function getFunctionName(node) {
|
|
|
14
14
|
const firstName = name?.name[0];
|
|
15
15
|
return firstName === void 0 ? void 0 : firstName.value.toLowerCase();
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function getColumnRef(node) {
|
|
18
18
|
const col = rec(node);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const column = node
|
|
19
|
+
return col?.["type"] === "column_ref" ? node : void 0;
|
|
20
|
+
}
|
|
21
|
+
function getColumnName(node) {
|
|
22
|
+
const column = getColumnRef(node)?.column;
|
|
23
23
|
return typeof column === "string" ? column.toLowerCase() : void 0;
|
|
24
24
|
}
|
|
25
25
|
function getColumnTable(node) {
|
|
26
|
-
|
|
27
|
-
if (col?.["type"] !== "column_ref") {
|
|
28
|
-
return void 0;
|
|
29
|
-
}
|
|
30
|
-
return node.table;
|
|
26
|
+
return getColumnRef(node)?.table;
|
|
31
27
|
}
|
|
32
28
|
function getStringValue(node) {
|
|
33
29
|
const val = rec(node);
|
|
@@ -40,80 +36,48 @@ function getNumberValue(node) {
|
|
|
40
36
|
const val = rec(node);
|
|
41
37
|
return val?.["type"] === "number" && typeof val["value"] === "number" ? val["value"] : void 0;
|
|
42
38
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
if (getFunctionName(node) !== "split") {
|
|
49
|
-
return false;
|
|
39
|
+
function getSplitUrlFunctionArgs(node, functionName) {
|
|
40
|
+
if (getFunctionName(node) !== functionName) {
|
|
41
|
+
return void 0;
|
|
50
42
|
}
|
|
51
|
-
const args =
|
|
43
|
+
const args = rec(node)?.["args"]?.value;
|
|
52
44
|
if (!Array.isArray(args) || args.length < 2) {
|
|
53
|
-
return
|
|
45
|
+
return void 0;
|
|
54
46
|
}
|
|
55
|
-
if (getColumnName(args[0]) !== "url") {
|
|
56
|
-
return
|
|
47
|
+
if (getColumnName(args[0]) !== "url" || getStringValue(args[1]) !== "/") {
|
|
48
|
+
return void 0;
|
|
57
49
|
}
|
|
58
|
-
|
|
50
|
+
return args;
|
|
51
|
+
}
|
|
52
|
+
function isSplitUrlIndexed(node) {
|
|
53
|
+
if (getSplitUrlFunctionArgs(node, "split") === void 0) {
|
|
59
54
|
return false;
|
|
60
55
|
}
|
|
61
|
-
|
|
56
|
+
const fn = rec(node);
|
|
57
|
+
return Array.isArray(fn?.["array_index"]) && fn["array_index"].length > 0;
|
|
62
58
|
}
|
|
63
59
|
function isSplitPartUrl(node) {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
if (getFunctionName(node) !== "split_part") {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
const args = fn["args"]?.value;
|
|
72
|
-
if (!Array.isArray(args) || args[2] === void 0) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
if (getColumnName(args[0]) !== "url") {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
return getStringValue(args[1]) === "/" && getNumberValue(args[2]) !== void 0;
|
|
60
|
+
const args = getSplitUrlFunctionArgs(node, "split_part");
|
|
61
|
+
return getNumberValue(args?.[2]) !== void 0;
|
|
79
62
|
}
|
|
80
63
|
function isCardinalitySplitUrl(node) {
|
|
81
|
-
const fn = rec(node);
|
|
82
|
-
if (fn?.["type"] !== "function") {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
64
|
if (getFunctionName(node) !== "cardinality") {
|
|
86
65
|
return false;
|
|
87
66
|
}
|
|
88
|
-
const outerArgs =
|
|
67
|
+
const outerArgs = rec(node)?.["args"]?.value;
|
|
89
68
|
if (!Array.isArray(outerArgs) || outerArgs.length === 0) {
|
|
90
69
|
return false;
|
|
91
70
|
}
|
|
92
|
-
|
|
93
|
-
if (innerFn?.["type"] !== "function") {
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
if (getFunctionName(outerArgs[0]) !== "split") {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
const innerArgs = innerFn["args"]?.value;
|
|
100
|
-
if (!Array.isArray(innerArgs) || innerArgs.length < 2) {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
return getColumnName(innerArgs[0]) === "url" && getStringValue(innerArgs[1]) === "/";
|
|
71
|
+
return getSplitUrlFunctionArgs(outerArgs[0], "split") !== void 0;
|
|
104
72
|
}
|
|
105
73
|
function getConditionTableQualifier(left) {
|
|
106
74
|
const colName = getColumnName(left);
|
|
107
75
|
if (colName !== void 0) {
|
|
108
76
|
return getColumnTable(left);
|
|
109
77
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return getColumnTable(
|
|
113
|
-
}
|
|
114
|
-
if (isSplitPartUrl(left)) {
|
|
115
|
-
const args = rec(left)?.["args"]?.value;
|
|
116
|
-
return getColumnTable(args?.[0]) ?? null;
|
|
78
|
+
const splitArgs = getSplitUrlFunctionArgs(left, "split") ?? getSplitUrlFunctionArgs(left, "split_part");
|
|
79
|
+
if (splitArgs !== void 0) {
|
|
80
|
+
return getColumnTable(splitArgs[0]) ?? null;
|
|
117
81
|
}
|
|
118
82
|
if (isCardinalitySplitUrl(left)) {
|
|
119
83
|
const outerArgs = rec(left)?.["args"]?.value;
|
|
@@ -123,6 +87,13 @@ function getConditionTableQualifier(left) {
|
|
|
123
87
|
}
|
|
124
88
|
return void 0;
|
|
125
89
|
}
|
|
90
|
+
function buildPathSegmentPredicate(index, value) {
|
|
91
|
+
return (path) => {
|
|
92
|
+
const part = path.split("/")[index - 1];
|
|
93
|
+
log("checking path segment", { path, index, part, value });
|
|
94
|
+
return part?.startsWith(":") === true ? true : part === value;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
126
97
|
function buildLeafPredicate(node, tableAlias) {
|
|
127
98
|
if (node.operator !== "=") {
|
|
128
99
|
return void 0;
|
|
@@ -148,25 +119,14 @@ function buildLeafPredicate(node, tableAlias) {
|
|
|
148
119
|
const index = left.array_index[0]?.index.value;
|
|
149
120
|
const value = getStringValue(right);
|
|
150
121
|
if (typeof index === "number" && value !== void 0) {
|
|
151
|
-
return (
|
|
152
|
-
const parts = path.split("/");
|
|
153
|
-
const part = parts[index - 1];
|
|
154
|
-
log(`checking path part`, { path, index, part, value });
|
|
155
|
-
return part?.startsWith(":") === true ? true : part === value;
|
|
156
|
-
};
|
|
122
|
+
return buildPathSegmentPredicate(index, value);
|
|
157
123
|
}
|
|
158
124
|
}
|
|
159
125
|
if (isSplitPartUrl(left)) {
|
|
160
|
-
const
|
|
161
|
-
const index = getNumberValue(args?.[2]);
|
|
126
|
+
const index = getNumberValue(getSplitUrlFunctionArgs(left, "split_part")?.[2]);
|
|
162
127
|
const value = getStringValue(right);
|
|
163
128
|
if (index !== void 0 && value !== void 0) {
|
|
164
|
-
return (
|
|
165
|
-
const parts = path.split("/");
|
|
166
|
-
const part = parts[index - 1];
|
|
167
|
-
log("checking split_part path part", { path, index, part, value });
|
|
168
|
-
return part?.startsWith(":") === true ? true : part === value;
|
|
169
|
-
};
|
|
129
|
+
return buildPathSegmentPredicate(index, value);
|
|
170
130
|
}
|
|
171
131
|
}
|
|
172
132
|
if (isCardinalitySplitUrl(left)) {
|
|
@@ -231,4 +191,4 @@ function matchApi(selectAST, tableAST, apiSchemas) {
|
|
|
231
191
|
export {
|
|
232
192
|
matchApi
|
|
233
193
|
};
|
|
234
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
194
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hcGktbWF0Y2hlci50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFFQSxPQUFPLFdBQVc7QUFNbEIsSUFBTSxNQUFNLE1BQU0sa0NBQWtDO0FBa0JwRCxJQUFNLGNBQWtDLE1BQU07QUFJOUMsU0FBUyxJQUFJLE1BQW9EO0FBQy9ELFNBQU8sT0FBTyxTQUFTLFlBQVksU0FBUyxPQUFRLE9BQW1DO0FBQ3pGO0FBRUEsU0FBUyxnQkFBZ0IsTUFBbUM7QUFDMUQsUUFBTSxLQUFLLElBQUksSUFBSTtBQUNuQixNQUFJLEtBQUssTUFBTSxNQUFNLFlBQVk7QUFDL0IsV0FBTztBQUFBLEVBQ1Q7QUFDQSxRQUFNLE9BQU8sR0FBRyxNQUFNO0FBQ3RCLFFBQU0sWUFBWSxNQUFNLEtBQUssQ0FBQztBQUM5QixTQUFPLGNBQWMsU0FBWSxTQUFZLFVBQVUsTUFBTSxZQUFZO0FBQzNFO0FBRUEsU0FBUyxhQUFhLE1BQTBDO0FBQzlELFFBQU0sTUFBTSxJQUFJLElBQUk7QUFDcEIsU0FBTyxNQUFNLE1BQU0sTUFBTSxlQUFnQixPQUF5QjtBQUNwRTtBQUVBLFNBQVMsY0FBYyxNQUFtQztBQUN4RCxRQUFNLFNBQVMsYUFBYSxJQUFJLEdBQUc7QUFDbkMsU0FBTyxPQUFPLFdBQVcsV0FBVyxPQUFPLFlBQVksSUFBSTtBQUM3RDtBQUVBLFNBQVMsZUFBZSxNQUEwQztBQUNoRSxTQUFPLGFBQWEsSUFBSSxHQUFHO0FBQzdCO0FBRUEsU0FBUyxlQUFlLE1BQW1DO0FBQ3pELFFBQU0sTUFBTSxJQUFJLElBQUk7QUFDcEIsTUFBSSxNQUFNLE1BQU0sTUFBTSx5QkFBeUIsTUFBTSxNQUFNLE1BQU0sVUFBVTtBQUN6RSxXQUFPO0FBQUEsRUFDVDtBQUNBLFNBQU8sT0FBTyxJQUFJLE9BQU8sTUFBTSxXQUFXLElBQUksT0FBTyxJQUFJO0FBQzNEO0FBRUEsU0FBUyxlQUFlLE1BQW1DO0FBQ3pELFFBQU0sTUFBTSxJQUFJLElBQUk7QUFDcEIsU0FB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
|