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

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 (80) hide show
  1. package/dist-mjs/athena/api-locator.mjs +30 -0
  2. package/dist-mjs/athena/api-matcher.mjs +108 -0
  3. package/dist-mjs/athena/athena.mjs +331 -0
  4. package/dist-mjs/athena/column.mjs +1 -0
  5. package/dist-mjs/athena/context.mjs +21 -0
  6. package/dist-mjs/athena/index.mjs +1 -0
  7. package/dist-mjs/athena/service-table.mjs +32 -0
  8. package/dist-mjs/athena/types.mjs +1 -0
  9. package/dist-mjs/athena/visitor.mjs +258 -0
  10. package/dist-mjs/index.mjs +8 -4
  11. package/dist-mjs/no-status-code-assert.mjs +1 -1
  12. package/dist-mjs/openapi/deref-schema.mjs +14 -0
  13. package/dist-mjs/openapi/generate-schema.mjs +273 -0
  14. package/dist-mjs/openapi/service-schema-generator.mjs +147 -0
  15. package/dist-mjs/peggy/athena-peggy.mjs +20629 -0
  16. package/dist-types/athena/api-locator.d.ts +2 -0
  17. package/dist-types/athena/api-matcher.d.ts +14 -0
  18. package/dist-types/athena/athena.d.ts +6 -0
  19. package/dist-types/athena/column.d.ts +1 -0
  20. package/dist-types/athena/context.d.ts +21 -0
  21. package/dist-types/athena/index.d.ts +8 -0
  22. package/dist-types/athena/service-table.d.ts +8 -0
  23. package/dist-types/athena/types.d.ts +474 -0
  24. package/dist-types/athena/visitor.d.ts +63 -0
  25. package/dist-types/no-status-code-assert.d.ts +1 -1
  26. package/dist-types/openapi/deref-schema.d.ts +1 -0
  27. package/dist-types/openapi/generate-schema.d.ts +33 -0
  28. package/dist-types/openapi/service-schema-generator.d.ts +5 -0
  29. package/dist-types/peggy/athena-peggy.d.ts +13 -0
  30. package/package.json +1 -96
  31. package/src/athena/ATHENA.md +387 -0
  32. package/src/athena/PLAN.md +355 -0
  33. package/src/athena/api-locator.ts +39 -0
  34. package/src/athena/api-matcher.ts +169 -0
  35. package/src/athena/athena.ts +491 -0
  36. package/src/athena/column.ts +2 -0
  37. package/src/athena/context.ts +47 -0
  38. package/src/athena/index.ts +11 -0
  39. package/src/athena/service-table.ts +55 -0
  40. package/src/athena/types.ts +526 -0
  41. package/src/athena/visitor.ts +365 -0
  42. package/src/index.ts +4 -0
  43. package/src/no-side-effects.ts +1 -1
  44. package/src/no-status-code-assert.ts +2 -2
  45. package/src/openapi/deref-schema.ts +14 -0
  46. package/src/openapi/generate-schema.ts +422 -0
  47. package/src/openapi/service-schema-generator.ts +189 -0
  48. package/src/peggy/athena-chat.peggy +608 -0
  49. package/src/peggy/athena-peggy.ts +22078 -0
  50. package/src/peggy/athena.peggy +2967 -0
  51. package/src/require-service-call-response-declaration.ts +2 -2
  52. package/src/services/interchange/v1/swagger.schema.deref.json +849 -0
  53. package/src/services/interchange/v1/swagger.schema.json +473 -0
  54. package/src/services/interchange/v1/swagger.yml +414 -0
  55. package/src/services/ledger/v1/swagger.schema.deref.json +6694 -0
  56. package/src/services/ledger/v1/swagger.schema.json +1820 -0
  57. package/src/services/ledger/v1/swagger.yml +1094 -0
  58. package/src/services/link/v1/swagger.schema.deref.json +648 -0
  59. package/src/services/link/v1/swagger.schema.json +444 -0
  60. package/src/services/link/v1/swagger.yml +343 -0
  61. package/src/services/message/v1/swagger.schema.deref.json +22049 -0
  62. package/src/services/message/v1/swagger.schema.json +3470 -0
  63. package/src/services/message/v1/swagger.yml +2798 -0
  64. package/src/services/message/v2/swagger.schema.deref.json +72221 -0
  65. package/src/services/message/v2/swagger.schema.json +3558 -0
  66. package/src/services/message/v2/swagger.yml +3009 -0
  67. package/src/services/paymentCard/v1/swagger.schema.deref.json +4346 -0
  68. package/src/services/paymentCard/v1/swagger.schema.json +2181 -0
  69. package/src/services/paymentCard/v1/swagger.yml +1161 -0
  70. package/src/services/paymentCard/v2/swagger.schema.deref.json +4336 -0
  71. package/src/services/paymentCard/v2/swagger.schema.json +2155 -0
  72. package/src/services/paymentCard/v2/swagger.yml +1149 -0
  73. package/src/services/person/v1/swagger.schema.deref.json +6786 -0
  74. package/src/services/person/v1/swagger.schema.json +1445 -0
  75. package/src/services/person/v1/swagger.yml +1157 -0
  76. package/src/services/teampayApproval/v1/swagger.schema.deref.json +9898 -0
  77. package/src/services/teampayCardManagement/v1/swagger.schema.deref.json +6187 -0
  78. package/src/services/teampayClientManagement/v1/swagger.schema.deref.json +4914 -0
  79. package/src/services/teampayClientManagement/v1/swagger.schema.json +1964 -0
  80. package/src/services/teampayClientManagement/v1/swagger.yml +1376 -0
@@ -0,0 +1,30 @@
1
+ // src/athena/api-locator.ts
2
+ import fs from "node:fs";
3
+ import debug from "debug";
4
+ import { generateSchemasForService } from "../openapi/generate-schema.mjs";
5
+ var log = debug("eslint-plugin:athena:api-locator");
6
+ var SERVICES_ROOT_FOLDER = "src/services";
7
+ function upperCaseFirstCharacter(value) {
8
+ return `${value[0]?.toUpperCase()}${value.slice(1)}`;
9
+ }
10
+ function locateApi(serviceName) {
11
+ log("locating API for service", serviceName);
12
+ const serviceNameParts = serviceName.split("-");
13
+ const camelCaseServiceName = [serviceNameParts[0], ...serviceNameParts.slice(1).map(upperCaseFirstCharacter)].join(
14
+ ""
15
+ );
16
+ const allSchemaFilenames = fs.globSync(`${SERVICES_ROOT_FOLDER}/${camelCaseServiceName}/*/swagger.schema.deref.json`);
17
+ log(`${allSchemaFilenames.length} versions of API schemas located for service ${serviceName}`, allSchemaFilenames);
18
+ if (allSchemaFilenames.length > 0) {
19
+ return allSchemaFilenames.map(
20
+ (schemaFilename) => JSON.parse(fs.readFileSync(schemaFilename, "utf-8"))
21
+ );
22
+ }
23
+ log("no pre-generated schemas found, attempting on-demand generation for service", serviceName);
24
+ const outputDir = `${SERVICES_ROOT_FOLDER}/${camelCaseServiceName}`;
25
+ return generateSchemasForService(serviceName, outputDir).map(({ schema }) => schema);
26
+ }
27
+ export {
28
+ locateApi
29
+ };
30
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hcGktbG9jYXRvci50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFFQSxPQUFPLFFBQVE7QUFFZixPQUFPLFdBQVc7QUFFbEIsU0FBMEIsaUNBQWlDO0FBRTNELElBQU0sTUFBTSxNQUFNLGtDQUFrQztBQUVwRCxJQUFNLHVCQUF1QjtBQUU3QixTQUFTLHdCQUF3QixPQUF1QjtBQUV0RCxTQUFPLEdBQUcsTUFBTSxDQUFDLEdBQUcsWUFBWSxDQUFDLEdBQUcsTUFBTSxNQUFNLENBQUMsQ0FBQztBQUNwRDtBQUVPLFNBQVMsVUFBVSxhQUFtQztBQUMzRCxNQUFJLDRCQUE0QixXQUFXO0FBRTNDLFFBQU0sbUJBQW1CLFlBQVksTUFBTSxHQUFHO0FBQzlDLFFBQU0sdUJBQXVCLENBQUMsaUJBQWlCLENBQUMsR0FBRyxHQUFHLGlCQUFpQixNQUFNLENBQUMsRUFBRSxJQUFJLHVCQUF1QixDQUFDLEVBQUU7QUFBQSxJQUM1RztBQUFBLEVBQ0Y7QUFFQSxRQUFNLHFCQUFxQixHQUFHLFNBQVMsR0FBRyxvQkFBb0IsSUFBSSxvQkFBb0IsOEJBQThCO0FBRXBILE1BQUksR0FBRyxtQkFBbUIsTUFBTSxnREFBZ0QsV0FBVyxJQUFJLGtCQUFrQjtBQUVqSCxNQUFJLG1CQUFtQixTQUFTLEdBQUc7QUFDakMsV0FBTyxtQkFBbUI7QUFBQSxNQUN4QixDQUFDLG1CQUFtQixLQUFLLE1BQU0sR0FBRyxhQUFhLGdCQUFnQixPQUFPLENBQUM7QUFBQSxJQUN6RTtBQUFBLEVBQ0Y7QUFFQSxNQUFJLCtFQUErRSxXQUFXO0FBQzlGLFFBQU0sWUFBWSxHQUFHLG9CQUFvQixJQUFJLG9CQUFvQjtBQUNqRSxTQUFPLDBCQUEwQixhQUFhLFNBQVMsRUFBRSxJQUFJLENBQUMsRUFBRSxPQUFPLE1BQU0sTUFBTTtBQUNyRjsiLAogICJuYW1lcyI6IFtdCn0K
@@ -0,0 +1,108 @@
1
+ // src/athena/api-matcher.ts
2
+ import debug from "debug";
3
+ import { JSONPath } from "jsonpath-plus";
4
+ var log = debug("eslint-plugin:athena:api-matcher");
5
+ function getVersionMatcher(_selectAST, _tableAST) {
6
+ return void 0;
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
+ };
28
+ }
29
+ return void 0;
30
+ }
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
+ };
41
+ }
42
+ return void 0;
43
+ }
44
+ function getPathMatchers(selectAST, tableAST) {
45
+ return [getPathPartMatcher(selectAST, tableAST), getPathPartsCountMatcher(selectAST, tableAST)];
46
+ }
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;
54
+ }
55
+ return void 0;
56
+ }
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;
63
+ }
64
+ 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(
71
+ ([path, operations]) => Object.entries(operations).map(([method, operationSchemas]) => ({
72
+ path,
73
+ method: method.toUpperCase(),
74
+ operationSchemas
75
+ }))
76
+ );
77
+ log("total operation schemas", allOperationSchemas.length);
78
+ const matchedOperationSchemas = allOperationSchemas.filter(
79
+ ({ path, method }) => schemaMatchers.every((matcher) => matcher(path, method))
80
+ );
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);
99
+ if (matchedApis.length === 0) {
100
+ log("no api satisfy both request and response matchers");
101
+ throw new Error("no matched api");
102
+ }
103
+ return matchedApis;
104
+ }
105
+ export {
106
+ matchApi
107
+ };
108
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hcGktbWF0Y2hlci50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFFQSxPQUFPLFdBQVc7QUFDbEIsU0FBUyxnQkFBZ0I7QUFLekIsSUFBTSxNQUFNLE1BQU0sa0NBQWtDO0FBa0JwRCxTQUFTLGtCQUFrQixZQUFvQixXQUF3QztBQUNyRixTQUFPO0FBQ1Q7QUFHQSxTQUFTLG1CQUFtQixXQUFtQixXQUF3QztBQUNyRixRQUFNLENBQUMsaUJBQWlCLElBQWMsU0FBUztBQUFBLElBQzdDLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxFQUNSLENBQUM7QUFHRCxNQUFJLHNCQUFzQixRQUFXO0FBQ25DLFVBQU0sQ0FBQyxhQUFhLElBQWMsU0FBUztBQUFBLE1BQ3pDLE1BQU07QUFBQSxNQUNOLE1BQU07QUFBQSxJQUNSLENBQUM7QUFDRCxVQUFNLENBQUMsYUFBYSxJQUFjLFNBQVM7QUFBQSxNQUN6QyxNQUFNO0FBQUEsTUFDTixNQUFNO0FBQUEsSUFDUixDQUFDO0FBRUQsV0FBTyxDQUFDLE1BQWMsWUFBb0I7QUFDeEMsWUFBTSxRQUFRLEtBQUssTUFBTSxHQUFHO0FBQzVCLFlBQU0sT0FBTyxNQUFNLGdCQUFnQixDQUFDO0FBQ3BDLFVBQUksc0JBQXNCLEVBQUUsTUFBTSxlQUFlLE1BQU0sY0FBYyxDQUFDO0FBQ3RFLGFBQU8sTUFBTSxXQUFXLEdBQUcsTUFBTSxPQUM3QixPQUNBLE1BQU0sZ0JBQWdCLENBQUMsTUFBTTtBQUFBLElBQ25DO0FBQUEsRUFDRjtBQUVBLFNBQU87QUFDVDtBQUdBLFNBQVMseUJBQXlCLFdBQW1CLFdBQXdDO0FBRTNGLFFBQU0sQ0FBQyxhQUFhLElBQWMsU0FBUztBQUFBLElBQ3pDLE1BQU07QUFBQSxJQUNOLE1BQU07QUFBQSxFQUNSLENBQUM7QUFFRCxNQUFJLGtCQUFrQixRQUFXO0FBRS9CLFdBQU8sQ0FBQyxNQUFjLFlBQW9CO0FBQ3hDLFlBQU0sUUFBUSxLQUFLLE1BQU0sR0FBRztB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
@@ -0,0 +1,331 @@
1
+ // src/athena/athena.ts
2
+ import { strict as assert } from "node:assert";
3
+ import debug from "debug";
4
+ import { JSONPath } from "jsonpath-plus";
5
+ import { ESLintUtils } from "@typescript-eslint/utils";
6
+ import { parse } from "../peggy/athena-peggy.mjs";
7
+ import { matchApi } from "./api-matcher.mjs";
8
+ import { locateApi } from "./api-locator.mjs";
9
+ import {
10
+ createChildContext,
11
+ createRootContext
12
+ } from "./context.mjs";
13
+ import { buildServiceTables } from "./service-table.mjs";
14
+ import {
15
+ extractBracketAccessorPath,
16
+ extractColumnRefs,
17
+ extractJsonExtractCalls,
18
+ extractJsonExtractPath,
19
+ hasFunctionCalls,
20
+ isBaseFrom,
21
+ isJoin,
22
+ isUnnestFrom
23
+ } from "./visitor.mjs";
24
+ var ruleId = "athena";
25
+ var log = debug("eslint-plugin:athena");
26
+ var createRule = ESLintUtils.RuleCreator((name) => name);
27
+ var SYNTEXT_ERROR = "SyntextError";
28
+ var ATHENA_ERROR = "AthenaError";
29
+ var AthenaError = class extends Error {
30
+ code;
31
+ constructor(code, message) {
32
+ super(message);
33
+ this.code = code;
34
+ this.name = "AthenaError";
35
+ }
36
+ };
37
+ function resolvedCol(name, schema, ast) {
38
+ return ast !== void 0 ? { name, schema, ast } : { name, schema };
39
+ }
40
+ function getApiSchemas(serviceName, ctx) {
41
+ let schemas = ctx.apiSchemas.get(serviceName);
42
+ if (schemas === void 0) {
43
+ schemas = locateApi(serviceName);
44
+ ctx.apiSchemas.set(serviceName, schemas);
45
+ }
46
+ return schemas;
47
+ }
48
+ function lookupTables(nameOrAlias, ctx) {
49
+ const canonical = ctx.aliases.get(nameOrAlias) ?? nameOrAlias;
50
+ return ctx.tables.get(canonical) ?? [];
51
+ }
52
+ function fromClauseItems(select) {
53
+ if (Array.isArray(select.from)) {
54
+ return select.from;
55
+ }
56
+ if (select.from !== null) {
57
+ return [select.from];
58
+ }
59
+ return [];
60
+ }
61
+ function resolveFromClause(select, ctx) {
62
+ for (const item of fromClauseItems(select)) {
63
+ if (isUnnestFrom(item)) {
64
+ continue;
65
+ }
66
+ if (isJoin(item)) {
67
+ const { table: tableName2, as: alias2 } = item;
68
+ if (alias2 !== null) {
69
+ ctx.aliases.set(alias2, tableName2);
70
+ }
71
+ if (!ctx.tables.has(tableName2)) {
72
+ const apiSchemas2 = getApiSchemas(tableName2, ctx);
73
+ const operations2 = matchApi(select, item, apiSchemas2) ?? [];
74
+ ctx.tables.set(tableName2, buildServiceTables(tableName2, operations2));
75
+ }
76
+ continue;
77
+ }
78
+ if (!isBaseFrom(item)) {
79
+ continue;
80
+ }
81
+ const { table: tableName, as: alias } = item;
82
+ if (alias !== null) {
83
+ ctx.aliases.set(alias, tableName);
84
+ }
85
+ if (ctx.tables.has(tableName)) {
86
+ continue;
87
+ }
88
+ const apiSchemas = getApiSchemas(tableName, ctx);
89
+ const operations = matchApi(select, item, apiSchemas) ?? [];
90
+ ctx.tables.set(tableName, buildServiceTables(tableName, operations));
91
+ }
92
+ }
93
+ function extractUnnestMappings(select) {
94
+ const mappings = [];
95
+ for (const item of fromClauseItems(select)) {
96
+ if (!isUnnestFrom(item)) {
97
+ continue;
98
+ }
99
+ const fromColumn = typeof item.expr.column === "string" ? item.expr.column : void 0;
100
+ assert.ok(fromColumn !== void 0, "UNNEST expr must be a column_ref with a string column name");
101
+ const toColumn = item.as?.args.value[0];
102
+ const toColName = toColumn !== void 0 && typeof toColumn.column === "string" ? toColumn.column : void 0;
103
+ assert.ok(toColName !== void 0, "UNNEST alias must be a column_ref with a string column name");
104
+ mappings.push({ fromColumn, toColumn: toColName });
105
+ }
106
+ return mappings;
107
+ }
108
+ function applyUnnestPre(mappings, ctx) {
109
+ const deferred = [];
110
+ for (const { fromColumn, toColumn } of mappings) {
111
+ const ownerTable = [...ctx.tables.values()].flat().find((table) => table.columns.has(fromColumn));
112
+ if (ownerTable === void 0) {
113
+ deferred.push({ fromColumn, toColumn });
114
+ continue;
115
+ }
116
+ const sourceColumns = ownerTable.columns.get(fromColumn) ?? [];
117
+ const sourceSchema = sourceColumns[0]?.schema;
118
+ assert.ok(sourceSchema?.type === "array", `UNNEST source column '${fromColumn}' must be an array schema`);
119
+ const unnestTableName = `${ownerTable.name ?? "<anonymous>"}:<unnested>`;
120
+ ctx.tables.set(unnestTableName, [
121
+ {
122
+ name: unnestTableName,
123
+ ...ownerTable.apiOperation !== void 0 ? { apiOperation: ownerTable.apiOperation } : {},
124
+ columns: /* @__PURE__ */ new Map([[toColumn, [resolvedCol(toColumn, sourceSchema.items, sourceColumns[0]?.ast)]]])
125
+ }
126
+ ]);
127
+ }
128
+ return deferred;
129
+ }
130
+ function applyUnnestPost(mappings, columns) {
131
+ for (const { fromColumn, toColumn } of mappings) {
132
+ const sourceColumns = columns.get(fromColumn);
133
+ assert.ok(sourceColumns !== void 0, `column ${fromColumn} not found in selected columns`);
134
+ const sourceSchema = sourceColumns[0]?.schema;
135
+ assert.ok(sourceSchema?.type === "array", `UNNEST source column '${fromColumn}' must be an array schema`);
136
+ columns.set(toColumn, [resolvedCol(toColumn, sourceSchema.items, sourceColumns[0]?.ast)]);
137
+ }
138
+ }
139
+ function resolveDefaultSchemaColumn(columnAlias, indexedName, columnAST, columns) {
140
+ const name = columnAlias ?? indexedName;
141
+ columns.set(name, [resolvedCol(name, { type: "string" }, columnAST)]);
142
+ }
143
+ function expandWildcard(referencedTables, columns) {
144
+ for (const table of referencedTables) {
145
+ for (const [colName, cols] of table.columns) {
146
+ columns.set(colName, cols);
147
+ }
148
+ }
149
+ }
150
+ function resolveSchemaAtPath(colRef, propertyAccessor, resolvedColumns) {
151
+ const adjustedPath = `$.${propertyAccessor.substring(1).replace(/(\.|\[)/gu, "..properties$1")}`;
152
+ log("adjusted path", adjustedPath);
153
+ const extractedSchemas = resolvedColumns.flatMap(
154
+ (col) => JSONPath({ json: col.schema, path: adjustedPath })
155
+ );
156
+ log("extracted schemas", extractedSchemas);
157
+ if (extractedSchemas.length === 0) {
158
+ throw new AthenaError(ATHENA_ERROR, `property not found ${colRef} - ${propertyAccessor}`);
159
+ }
160
+ return extractedSchemas;
161
+ }
162
+ function navigateSchemaPath(colRef, propertyAccessor, resolvedColumns, colName, columnAST, columns) {
163
+ const extractedSchemas = resolveSchemaAtPath(colRef, propertyAccessor, resolvedColumns);
164
+ columns.set(
165
+ colName,
166
+ extractedSchemas.map((schema) => resolvedCol(colName, schema, columnAST))
167
+ );
168
+ }
169
+ function validateComplexColumnExpression(columnAST, allTables, ctx) {
170
+ for (const { ref, path } of extractJsonExtractCalls(columnAST)) {
171
+ const tableRef = ref.table ?? void 0;
172
+ const colRef = typeof ref.column === "string" ? ref.column : void 0;
173
+ if (colRef === void 0) {
174
+ continue;
175
+ }
176
+ const referencedTables = tableRef !== void 0 ? lookupTables(tableRef, ctx) : allTables;
177
+ const resolvedColumns = referencedTables.flatMap((table) => table.columns.get(colRef) ?? []);
178
+ if (resolvedColumns.length > 0) {
179
+ resolveSchemaAtPath(colRef, path, resolvedColumns);
180
+ }
181
+ }
182
+ }
183
+ function resolveSingleColumnRef(columnAST, columnAlias, indexedName, ref, allTables, ctx, columns) {
184
+ const tableRef = ref.table ?? void 0;
185
+ const colRef = typeof ref.column === "string" ? ref.column : void 0;
186
+ assert.ok(colRef !== void 0, "column_ref must have a string column name");
187
+ const referencedTables = tableRef !== void 0 ? lookupTables(tableRef, ctx) : allTables;
188
+ assert.ok(referencedTables.length > 0, `no tables found for column reference '${colRef}'`);
189
+ if (colRef === "*") {
190
+ expandWildcard(referencedTables, columns);
191
+ return;
192
+ }
193
+ const withFunctions = hasFunctionCalls(columnAST);
194
+ const colName = columnAlias ?? (withFunctions ? indexedName : colRef);
195
+ const resolvedColumns = referencedTables.flatMap((table) => table.columns.get(colRef) ?? []);
196
+ if (resolvedColumns.length === 0) {
197
+ const tableNames = [...ctx.tables.keys()].join(", ");
198
+ throw new AthenaError(ATHENA_ERROR, `can't found column ${colRef} in tables: ${tableNames}`);
199
+ }
200
+ const propertyAccessor = extractJsonExtractPath(columnAST) ?? extractBracketAccessorPath(columnAST);
201
+ if (propertyAccessor !== void 0) {
202
+ navigateSchemaPath(colRef, propertyAccessor, resolvedColumns, colName, columnAST, columns);
203
+ return;
204
+ }
205
+ columns.set(
206
+ colName,
207
+ resolvedColumns.map((col) => resolvedCol(colName, col.schema, columnAST))
208
+ );
209
+ }
210
+ function resolveSelectColumns(select, ctx) {
211
+ const allTables = [...ctx.tables.values()].flat();
212
+ const columns = /* @__PURE__ */ new Map();
213
+ for (const [index, columnAST] of select.columns.entries()) {
214
+ log("resolving column", columnAST);
215
+ const columnAlias = columnAST.as ?? null;
216
+ const indexedName = `_col${String(index)}`;
217
+ const columnRefs = extractColumnRefs(columnAST);
218
+ if (columnRefs.length !== 1) {
219
+ validateComplexColumnExpression(columnAST, allTables, ctx);
220
+ resolveDefaultSchemaColumn(columnAlias, indexedName, columnAST, columns);
221
+ continue;
222
+ }
223
+ const [ref] = columnRefs;
224
+ assert.ok(ref !== void 0);
225
+ resolveSingleColumnRef(columnAST, columnAlias, indexedName, ref, allTables, ctx, columns);
226
+ }
227
+ return columns;
228
+ }
229
+ function checkSelect(selectAST, ctx, withTableName) {
230
+ const select = "stmt" in selectAST ? selectAST.stmt.ast : selectAST;
231
+ const selectCtx = createChildContext(ctx);
232
+ resolveFromClause(select, selectCtx);
233
+ const unnestMappings = extractUnnestMappings(select);
234
+ const deferredUnnest = applyUnnestPre(unnestMappings, selectCtx);
235
+ const columns = resolveSelectColumns(select, selectCtx);
236
+ applyUnnestPost(deferredUnnest, columns);
237
+ log("resolved columns", [...columns.keys()]);
238
+ if (select._next !== void 0) {
239
+ checkSelect(select._next, ctx, withTableName);
240
+ }
241
+ if (withTableName !== void 0) {
242
+ const resolvedTable = { name: withTableName, columns };
243
+ ctx.tables.set(withTableName, [resolvedTable]);
244
+ }
245
+ }
246
+ function checkAthenaAst(ast, ctx) {
247
+ assert.ok(ast.type === "select");
248
+ const select = ast;
249
+ if (select.with !== null) {
250
+ for (const withItem of select.with) {
251
+ checkSelect(withItem.stmt.ast, ctx, withItem.name.value);
252
+ }
253
+ select.with = null;
254
+ }
255
+ checkSelect(select, ctx);
256
+ }
257
+ var rule = createRule({
258
+ name: ruleId,
259
+ meta: {
260
+ type: "problem",
261
+ docs: {
262
+ description: "Validate Athena SQL strings against OpenAPI schemas at lint time"
263
+ },
264
+ schema: [],
265
+ messages: {
266
+ [SYNTEXT_ERROR]: `SyntextError {{ errorMessage }}`,
267
+ [ATHENA_ERROR]: `AthenaError {{ errorMessage }}`
268
+ }
269
+ },
270
+ defaultOptions: [],
271
+ create(context) {
272
+ function checkSql(sql, sqlNode) {
273
+ if (!/^\s*(?:SELECT\b[\s\S]*\bFROM\b|WITH\b[\s\S]*\bSELECT\b[\s\S]*\b)/iu.test(sql)) {
274
+ log("skipping non-SELECT SQL string", { sql });
275
+ return;
276
+ }
277
+ let ast;
278
+ try {
279
+ ({ ast } = parse(sql, { includeLocations: true }));
280
+ } catch (error) {
281
+ log("error checking Athena AST", { error, sql });
282
+ context.report({
283
+ node: sqlNode,
284
+ messageId: SYNTEXT_ERROR,
285
+ data: { errorMessage: JSON.stringify(error, void 0, 2), sql }
286
+ });
287
+ return;
288
+ }
289
+ const athenaCtx = createRootContext();
290
+ try {
291
+ checkAthenaAst(Array.isArray(ast) ? ast[0] : ast, athenaCtx);
292
+ } catch (error) {
293
+ log("error checking Athena AST", { error, sql });
294
+ if (error instanceof AthenaError) {
295
+ context.report({
296
+ node: sqlNode,
297
+ messageId: ATHENA_ERROR,
298
+ data: { errorMessage: error.message }
299
+ });
300
+ } else {
301
+ console.error(`Failed to apply ${ruleId} rule for "${context.filename}":`, error);
302
+ context.report({
303
+ node: sqlNode,
304
+ messageId: ATHENA_ERROR,
305
+ data: {
306
+ errorMessage: error instanceof Error ? String(error) : JSON.stringify(error, void 0, 2)
307
+ }
308
+ });
309
+ }
310
+ }
311
+ }
312
+ return {
313
+ TemplateLiteral(sqlNode) {
314
+ const sql = sqlNode.quasis.map((quasi) => quasi.value.cooked).join("").trim();
315
+ checkSql(sql, sqlNode);
316
+ },
317
+ Literal(sqlNode) {
318
+ if (typeof sqlNode.value !== "string") {
319
+ return;
320
+ }
321
+ checkSql(sqlNode.value, sqlNode);
322
+ }
323
+ };
324
+ }
325
+ });
326
+ var athena_default = rule;
327
+ export {
328
+ athena_default as default,
329
+ ruleId
330
+ };
331
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hdGhlbmEudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBUUEsU0FBUyxVQUFVLGNBQWM7QUFFakMsT0FBTyxXQUFXO0FBQ2xCLFNBQVMsZ0JBQWdCO0FBQ3pCLFNBQVMsbUJBQWtDO0FBRzNDLFNBQVMsYUFBYTtBQUV0QixTQUFTLGdCQUFnQjtBQUN6QixTQUFTLGlCQUFpQjtBQUMxQjtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FJSztBQUNQLFNBQVMsMEJBQTBCO0FBQ25DO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBRUEsSUFBTSxTQUFTO0FBRXRCLElBQU0sTUFBTSxNQUFNLHNCQUFzQjtBQUN4QyxJQUFNLGFBQWEsWUFBWSxZQUFZLENBQUMsU0FBUyxJQUFJO0FBRXpELElBQU0sZ0JBQWdCO0FBQ3RCLElBQU0sZUFBZTtBQUVyQixJQUFNLGNBQU4sY0FBMEIsTUFBTTtBQUFBLEVBQ3ZCO0FBQUEsRUFDUCxZQUFZLE1BQWMsU0FBaUI7QUFDekMsVUFBTSxPQUFPO0FBQ2IsU0FBSyxPQUFPO0FBQ1osU0FBSyxPQUFPO0FBQUEsRUFDZDtBQUNGO0FBTUEsU0FBUyxZQUFZLE1BQWMsUUFBc0IsS0FBOEI7QUFDckYsU0FBTyxRQUFRLFNBQVksRUFBRSxNQUFNLFFBQVEsSUFBSSxJQUFJLEVBQUUsTUFBTSxPQUFPO0FBQ3BFO0FBR0EsU0FBUyxjQUFjLGFBQXFCLEtBQW1CO0FBQzdELE1BQUksVUFBVSxJQUFJLFdBQVcsSUFBSSxXQUFXO0FBQzVDLE1BQUksWUFBWSxRQUFXO0FBQ3pCLGNBQVUsVUFBVSxXQUFXO0FBQy9CLFFBQUksV0FBVyxJQUFJLGFBQWEsT0FBTztBQUFBLEVBQ3pDO0FBQ0EsU0FBTztBQUNUO0FBR0EsU0FBUyxhQUFhLGFBQXFCLEtBQW9DO0FBQzdFLFFBQU0sWUFBWSxJ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
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFtdLAogICJtYXBwaW5ncyI6ICIiLAogICJuYW1lcyI6IFtdCn0K
@@ -0,0 +1,21 @@
1
+ // src/athena/context.ts
2
+ function createRootContext() {
3
+ return {
4
+ tables: /* @__PURE__ */ new Map(),
5
+ aliases: /* @__PURE__ */ new Map(),
6
+ apiSchemas: /* @__PURE__ */ new Map()
7
+ };
8
+ }
9
+ function createChildContext(parent) {
10
+ return {
11
+ tables: new Map(parent.tables),
12
+ aliases: /* @__PURE__ */ new Map(),
13
+ apiSchemas: parent.apiSchemas,
14
+ parent
15
+ };
16
+ }
17
+ export {
18
+ createChildContext,
19
+ createRootContext
20
+ };
21
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9jb250ZXh0LnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQThCTyxTQUFTLG9CQUFrQztBQUNoRCxTQUFPO0FBQUEsSUFDTCxRQUFRLG9CQUFJLElBQUk7QUFBQSxJQUNoQixTQUFTLG9CQUFJLElBQUk7QUFBQSxJQUNqQixZQUFZLG9CQUFJLElBQUk7QUFBQSxFQUN0QjtBQUNGO0FBR08sU0FBUyxtQkFBbUIsUUFBb0M7QUFDckUsU0FBTztBQUFBLElBQ0wsUUFBUSxJQUFJLElBQUksT0FBTyxNQUFNO0FBQUEsSUFDN0IsU0FBUyxvQkFBSSxJQUFJO0FBQUEsSUFDakIsWUFBWSxPQUFPO0FBQUEsSUFDbkI7QUFBQSxFQUNGO0FBQ0Y7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFtdLAogICJtYXBwaW5ncyI6ICIiLAogICJuYW1lcyI6IFtdCn0K
@@ -0,0 +1,32 @@
1
+ // src/athena/service-table.ts
2
+ var SCHEMA_STRING = { type: "string" };
3
+ var SCHEMA_OBJECT = { type: "object" };
4
+ function col(name, schema) {
5
+ return { name, schema };
6
+ }
7
+ function bodySchema(envelope, field) {
8
+ return envelope["properties"]?.[field] ?? SCHEMA_OBJECT;
9
+ }
10
+ function buildServiceTables(tableName, operations) {
11
+ return operations.map((operation) => ({
12
+ name: tableName,
13
+ apiOperation: [operation],
14
+ columns: /* @__PURE__ */ new Map([
15
+ ["method", [col("method", SCHEMA_STRING)]],
16
+ ["started", [col("started", SCHEMA_STRING)]],
17
+ ["ended", [col("ended", SCHEMA_STRING)]],
18
+ ["url", [col("url", SCHEMA_STRING)]],
19
+ ["requestbody", [col("requestbody", bodySchema(operation.request, "body"))]],
20
+ ["requestheaders", [col("requestheaders", bodySchema(operation.request, "headers"))]],
21
+ ["responsestatus", [col("responsestatus", SCHEMA_STRING)]],
22
+ ["responsemessage", [col("responsemessage", SCHEMA_STRING)]],
23
+ ["responsetype", [col("responsetype", SCHEMA_STRING)]],
24
+ ["responsebody", [col("responsebody", bodySchema(operation.response, "body"))]],
25
+ ["responseheaders", [col("responseheaders", bodySchema(operation.response, "headers"))]]
26
+ ])
27
+ }));
28
+ }
29
+ export {
30
+ buildServiceTables
31
+ };
32
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9zZXJ2aWNlLXRhYmxlLnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQW9CQSxJQUFNLGdCQUE4QixFQUFFLE1BQU0sU0FBUztBQUNyRCxJQUFNLGdCQUE4QixFQUFFLE1BQU0sU0FBUztBQUVyRCxTQUFTLElBQUksTUFBYyxRQUF5QztBQUNsRSxTQUFPLEVBQUUsTUFBTSxPQUFPO0FBQ3hCO0FBRUEsU0FBUyxXQUFXLFVBQXdCLE9BQTRDO0FBQ3RGLFNBQVEsU0FBNkQsWUFBWSxJQUFJLEtBQUssS0FBSztBQUNqRztBQU9PLFNBQVMsbUJBQW1CLFdBQW1CLFlBQWlEO0FBQ3JHLFNBQU8sV0FBVyxJQUFJLENBQUMsZUFBZTtBQUFBLElBQ3BDLE1BQU07QUFBQSxJQUNOLGNBQWMsQ0FBQyxTQUFTO0FBQUEsSUFDeEIsU0FBUyxvQkFBSSxJQUE4QjtBQUFBLE1BQ3pDLENBQUMsVUFBVSxDQUFDLElBQUksVUFBVSxhQUFhLENBQUMsQ0FBQztBQUFBLE1BQ3pDLENBQUMsV0FBVyxDQUFDLElBQUksV0FBVyxhQUFhLENBQUMsQ0FBQztBQUFBLE1BQzNDLENBQUMsU0FBUyxDQUFDLElBQUksU0FBUyxhQUFhLENBQUMsQ0FBQztBQUFBLE1BQ3ZDLENBQUMsT0FBTyxDQUFDLElBQUksT0FBTyxhQUFhLENBQUMsQ0FBQztBQUFBLE1BQ25DLENBQUMsZUFBZSxDQUFDLElBQUksZUFBZSxXQUFXLFVBQVUsU0FBUyxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQUEsTUFDM0UsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLGtCQUFrQixXQUFXLFVBQVUsU0FBUyxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBQUEsTUFDcEYsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLGtCQUFrQixhQUFhLENBQUMsQ0FBQztBQUFBLE1BQ3pELENBQUMsbUJBQW1CLENBQUMsSUFBSSxtQkFBbUIsYUFBYSxDQUFDLENBQUM7QUFBQSxNQUMzRCxDQUFDLGdCQUFnQixDQUFDLElBQUksZ0JBQWdCLGFBQWEsQ0FBQyxDQUFDO0FBQUEsTUFDckQsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLGdCQUFnQixXQUFXLFVBQVUsVUFBVSxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQUEsTUFDOUUsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLG1CQUFtQixXQUFXLFVBQVUsVUFBVSxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBQUEsSUFDekYsQ0FBQztBQUFBLEVBQ0gsRUFBRTtBQUNKOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFtdLAogICJtYXBwaW5ncyI6ICIiLAogICJuYW1lcyI6IFtdCn0K