@checkdigit/eslint-plugin 7.18.0-PR.143-b6d4 → 7.18.0-PR.143-c73c
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/LICENSE.txt +1 -1
- package/dist-mjs/athena/athena.mjs +3 -473
- package/dist-mjs/athena/sql-file.mjs +100 -0
- package/dist-mjs/athena/validate.mjs +480 -0
- package/dist-mjs/index.mjs +18 -5
- package/dist-mjs/sql-parser.mjs +25 -0
- package/dist-types/athena/athena.d.ts +1 -2
- package/dist-types/athena/sql-file.d.ts +5 -0
- package/dist-types/athena/validate.d.ts +14 -0
- package/dist-types/index.d.ts +1 -0
- package/dist-types/sql-parser.d.ts +25 -0
- package/package.json +1 -1
- package/src/athena/athena.ts +3 -654
- package/src/athena/sql-file.ts +116 -0
- package/src/athena/validate.ts +625 -0
- package/src/index.ts +12 -0
- package/src/sql-parser.ts +46 -0
- package/src/athena/ATHENA.md +0 -387
- package/src/athena/PLAN.md +0 -355
package/LICENSE.txt
CHANGED
|
@@ -1,52 +1,12 @@
|
|
|
1
1
|
// src/athena/athena.ts
|
|
2
|
-
import { strict as assert } from "node:assert";
|
|
3
2
|
import debug from "debug";
|
|
4
|
-
import { JSONPath } from "jsonpath-plus";
|
|
5
3
|
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
6
4
|
import { parse } from "../peggy/athena-peggy.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
createChildContext,
|
|
11
|
-
createRootContext
|
|
12
|
-
} from "./context.mjs";
|
|
13
|
-
import { buildServiceTables } from "./service-table.mjs";
|
|
14
|
-
import {
|
|
15
|
-
containsCastToArray,
|
|
16
|
-
containsCastToMap,
|
|
17
|
-
containsLambda,
|
|
18
|
-
extractBracketAccessorPath,
|
|
19
|
-
extractColumnRefs,
|
|
20
|
-
extractJsonExtractCalls,
|
|
21
|
-
extractJsonExtractPath,
|
|
22
|
-
hasFunctionCalls,
|
|
23
|
-
isBaseFrom,
|
|
24
|
-
isJoin,
|
|
25
|
-
isTableExpr,
|
|
26
|
-
isUnnestFrom
|
|
27
|
-
} from "./visitor.mjs";
|
|
5
|
+
import { createRootContext } from "./context.mjs";
|
|
6
|
+
import { ATHENA_ERROR, AthenaError, checkAthenaAst, offsetToLoc, SYNTEXT_ERROR } from "./validate.mjs";
|
|
28
7
|
var ruleId = "athena";
|
|
29
8
|
var log = debug("eslint-plugin:athena");
|
|
30
9
|
var createRule = ESLintUtils.RuleCreator((name) => name);
|
|
31
|
-
var SYNTEXT_ERROR = "SyntextError";
|
|
32
|
-
var ATHENA_ERROR = "AthenaError";
|
|
33
|
-
var AthenaError = class extends Error {
|
|
34
|
-
code;
|
|
35
|
-
ast;
|
|
36
|
-
constructor(code, message, ast) {
|
|
37
|
-
super(message);
|
|
38
|
-
this.code = code;
|
|
39
|
-
this.name = "AthenaError";
|
|
40
|
-
if (ast !== void 0) {
|
|
41
|
-
this.ast = ast;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
function offsetToLoc(text, offset) {
|
|
46
|
-
const prefix = text.slice(0, offset);
|
|
47
|
-
const lines = prefix.split("\n");
|
|
48
|
-
return { line: lines.length, column: lines[lines.length - 1]?.length ?? 0 };
|
|
49
|
-
}
|
|
50
10
|
function buildSqlMapping(sqlNode) {
|
|
51
11
|
if (sqlNode.type !== AST_NODE_TYPES.TemplateLiteral) {
|
|
52
12
|
return [{ sqlStart: 0, srcStart: sqlNode.range[0] + 1 }];
|
|
@@ -72,436 +32,6 @@ function sqlOffsetToSource(sqlOffset, segments) {
|
|
|
72
32
|
}
|
|
73
33
|
return segments[0]?.srcStart ?? 0;
|
|
74
34
|
}
|
|
75
|
-
function resolvedCol(name, schema, ast) {
|
|
76
|
-
return ast !== void 0 ? { name, schema, ast } : { name, schema };
|
|
77
|
-
}
|
|
78
|
-
function getApiSchemas(serviceName, ctx) {
|
|
79
|
-
let schemas = ctx.apiSchemas.get(serviceName);
|
|
80
|
-
if (schemas === void 0) {
|
|
81
|
-
schemas = locateApi(serviceName);
|
|
82
|
-
ctx.apiSchemas.set(serviceName, schemas);
|
|
83
|
-
}
|
|
84
|
-
return schemas;
|
|
85
|
-
}
|
|
86
|
-
function lookupTables(nameOrAlias, ctx) {
|
|
87
|
-
const canonical = ctx.aliases.get(nameOrAlias) ?? nameOrAlias;
|
|
88
|
-
return ctx.tables.get(canonical) ?? [];
|
|
89
|
-
}
|
|
90
|
-
function fromClauseItems(select) {
|
|
91
|
-
if (Array.isArray(select.from)) {
|
|
92
|
-
return select.from;
|
|
93
|
-
}
|
|
94
|
-
if (select.from !== null) {
|
|
95
|
-
return [select.from];
|
|
96
|
-
}
|
|
97
|
-
return [];
|
|
98
|
-
}
|
|
99
|
-
function resolveServiceTable(select, item, ctx) {
|
|
100
|
-
const { table: tableName } = item;
|
|
101
|
-
try {
|
|
102
|
-
const apiSchemas = getApiSchemas(tableName, ctx);
|
|
103
|
-
if (apiSchemas.length === 0) {
|
|
104
|
-
throw new AthenaError(ATHENA_ERROR, `service not found: "${tableName}" (no swagger schema located)`, item);
|
|
105
|
-
}
|
|
106
|
-
const operations = matchApi(select, item, apiSchemas) ?? [];
|
|
107
|
-
ctx.tables.set(tableName, buildServiceTables(tableName, operations));
|
|
108
|
-
} catch (error) {
|
|
109
|
-
if (error instanceof AthenaError) {
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
112
|
-
throw new AthenaError(ATHENA_ERROR, error instanceof Error ? error.message : String(error), item);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
function restrictToFromClause(select, ctx) {
|
|
116
|
-
const fromNames = /* @__PURE__ */ new Set();
|
|
117
|
-
for (const item of fromClauseItems(select)) {
|
|
118
|
-
if (isBaseFrom(item) || isJoin(item)) {
|
|
119
|
-
fromNames.add(item.table);
|
|
120
|
-
} else if (isTableExpr(item)) {
|
|
121
|
-
fromNames.add(typeof item.as === "string" ? item.as : "<subquery>");
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
for (const name of [...ctx.tables.keys()]) {
|
|
125
|
-
if (!fromNames.has(name)) {
|
|
126
|
-
ctx.tables.delete(name);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function resolveFromClause(select, ctx) {
|
|
131
|
-
for (const item of fromClauseItems(select)) {
|
|
132
|
-
if (isUnnestFrom(item)) {
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
if (isTableExpr(item)) {
|
|
136
|
-
const alias2 = typeof item.as === "string" ? item.as : "<subquery>";
|
|
137
|
-
checkSelect(item.expr.ast, ctx, alias2);
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
if (isJoin(item)) {
|
|
141
|
-
const { table: tableName2, as: alias2 } = item;
|
|
142
|
-
if (alias2 !== null) {
|
|
143
|
-
ctx.aliases.set(alias2, tableName2);
|
|
144
|
-
}
|
|
145
|
-
if (!ctx.tables.has(tableName2)) {
|
|
146
|
-
resolveServiceTable(select, item, ctx);
|
|
147
|
-
}
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
if (!isBaseFrom(item)) {
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
const { table: tableName, as: alias } = item;
|
|
154
|
-
if (alias !== null) {
|
|
155
|
-
ctx.aliases.set(alias, tableName);
|
|
156
|
-
}
|
|
157
|
-
if (ctx.tables.has(tableName)) {
|
|
158
|
-
continue;
|
|
159
|
-
}
|
|
160
|
-
resolveServiceTable(select, item, ctx);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
function extractUnnestMappings(select) {
|
|
164
|
-
const mappings = [];
|
|
165
|
-
for (const item of fromClauseItems(select)) {
|
|
166
|
-
if (!isUnnestFrom(item)) {
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
const fromColumn = typeof item.expr.column === "string" ? item.expr.column : void 0;
|
|
170
|
-
assert.ok(fromColumn !== void 0, "UNNEST expr must be a column_ref with a string column name");
|
|
171
|
-
const aliasArgs = item.as?.args.value ?? [];
|
|
172
|
-
const toColumns = [];
|
|
173
|
-
for (const col of aliasArgs) {
|
|
174
|
-
if (typeof col.column === "string") {
|
|
175
|
-
toColumns.push(col.column);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
assert.ok(toColumns.length > 0, "UNNEST alias must have at least one column name");
|
|
179
|
-
mappings.push({ fromColumn, toColumns, ast: item.expr });
|
|
180
|
-
}
|
|
181
|
-
return mappings;
|
|
182
|
-
}
|
|
183
|
-
function applyUnnestPre(mappings, ctx) {
|
|
184
|
-
const deferred = [];
|
|
185
|
-
for (const { fromColumn, toColumns, ast } of mappings) {
|
|
186
|
-
const ownerTable = [...ctx.tables.values()].flat().find((table) => table.columns.has(fromColumn));
|
|
187
|
-
if (ownerTable === void 0) {
|
|
188
|
-
deferred.push({ fromColumn, toColumns, ast });
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
const sourceColumns = ownerTable.columns.get(fromColumn) ?? [];
|
|
192
|
-
const sourceSchema = sourceColumns[0]?.schema;
|
|
193
|
-
const unnestTableName = `${ownerTable.name ?? "<anonymous>"}:<unnested>`;
|
|
194
|
-
const apiOperation = ownerTable.apiOperation !== void 0 ? { apiOperation: ownerTable.apiOperation } : {};
|
|
195
|
-
if (sourceSchema?.type === "array") {
|
|
196
|
-
const [toColumn] = toColumns;
|
|
197
|
-
assert.ok(toColumn !== void 0);
|
|
198
|
-
ctx.tables.set(unnestTableName, [
|
|
199
|
-
{
|
|
200
|
-
name: unnestTableName,
|
|
201
|
-
...apiOperation,
|
|
202
|
-
columns: /* @__PURE__ */ new Map([[toColumn, [resolvedCol(toColumn, sourceSchema.items, sourceColumns[0]?.ast)]]])
|
|
203
|
-
}
|
|
204
|
-
]);
|
|
205
|
-
} else if (sourceSchema?.type === "object") {
|
|
206
|
-
const [keyColumn, valueColumn] = toColumns;
|
|
207
|
-
assert.ok(
|
|
208
|
-
keyColumn !== void 0 && valueColumn !== void 0,
|
|
209
|
-
`UNNEST of map column '${fromColumn}' requires exactly two alias columns (key, value)`
|
|
210
|
-
);
|
|
211
|
-
const addlProps = sourceSchema["additionalProperties"];
|
|
212
|
-
const valueSchema = typeof addlProps === "object" && addlProps !== null ? addlProps : { type: "string" };
|
|
213
|
-
ctx.tables.set(unnestTableName, [
|
|
214
|
-
{
|
|
215
|
-
name: unnestTableName,
|
|
216
|
-
...apiOperation,
|
|
217
|
-
columns: /* @__PURE__ */ new Map([
|
|
218
|
-
[keyColumn, [resolvedCol(keyColumn, { type: "string" }, sourceColumns[0]?.ast)]],
|
|
219
|
-
[valueColumn, [resolvedCol(valueColumn, valueSchema, sourceColumns[0]?.ast)]]
|
|
220
|
-
])
|
|
221
|
-
}
|
|
222
|
-
]);
|
|
223
|
-
} else {
|
|
224
|
-
throw new AthenaError(
|
|
225
|
-
ATHENA_ERROR,
|
|
226
|
-
`UNNEST source column '${fromColumn}' must resolve to an array or map schema`,
|
|
227
|
-
ast
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return deferred;
|
|
232
|
-
}
|
|
233
|
-
function applyUnnestPost(mappings, columns) {
|
|
234
|
-
for (const { fromColumn, toColumns, ast } of mappings) {
|
|
235
|
-
const sourceColumns = columns.get(fromColumn);
|
|
236
|
-
if (sourceColumns === void 0) {
|
|
237
|
-
throw new AthenaError(ATHENA_ERROR, `UNNEST source column '${fromColumn}' not found in SELECT`, ast);
|
|
238
|
-
}
|
|
239
|
-
const sourceSchema = sourceColumns[0]?.schema;
|
|
240
|
-
if (sourceSchema?.type === "array") {
|
|
241
|
-
const [toColumn] = toColumns;
|
|
242
|
-
assert.ok(toColumn !== void 0);
|
|
243
|
-
columns.set(toColumn, [resolvedCol(toColumn, sourceSchema.items, sourceColumns[0]?.ast)]);
|
|
244
|
-
} else if (sourceSchema?.type === "object") {
|
|
245
|
-
const [keyColumn, valueColumn] = toColumns;
|
|
246
|
-
assert.ok(
|
|
247
|
-
keyColumn !== void 0 && valueColumn !== void 0,
|
|
248
|
-
`UNNEST of map column '${fromColumn}' requires exactly two alias columns (key, value)`
|
|
249
|
-
);
|
|
250
|
-
const addlProps = sourceSchema["additionalProperties"];
|
|
251
|
-
const valueSchema = typeof addlProps === "object" && addlProps !== null ? addlProps : { type: "string" };
|
|
252
|
-
columns.set(keyColumn, [resolvedCol(keyColumn, { type: "string" }, sourceColumns[0]?.ast)]);
|
|
253
|
-
columns.set(valueColumn, [resolvedCol(valueColumn, valueSchema, sourceColumns[0]?.ast)]);
|
|
254
|
-
} else {
|
|
255
|
-
throw new AthenaError(
|
|
256
|
-
ATHENA_ERROR,
|
|
257
|
-
`UNNEST source column '${fromColumn}' must resolve to an array or map schema`,
|
|
258
|
-
ast
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
function resolveDefaultSchemaColumn(columnAlias, indexedName, columnAST, columns) {
|
|
264
|
-
const name = columnAlias ?? indexedName;
|
|
265
|
-
columns.set(name, [resolvedCol(name, { type: "string" }, columnAST)]);
|
|
266
|
-
}
|
|
267
|
-
function expandWildcard(referencedTables, columns) {
|
|
268
|
-
for (const table of referencedTables) {
|
|
269
|
-
for (const [colName, cols] of table.columns) {
|
|
270
|
-
columns.set(colName, cols);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
function schemaPropertyHint(resolvedColumns) {
|
|
275
|
-
if (resolvedColumns.length === 0) {
|
|
276
|
-
return "";
|
|
277
|
-
}
|
|
278
|
-
const first = JSON.stringify(resolvedColumns[0]?.schema);
|
|
279
|
-
if (!resolvedColumns.every((col) => JSON.stringify(col.schema) === first)) {
|
|
280
|
-
return "";
|
|
281
|
-
}
|
|
282
|
-
const schema = resolvedColumns[0]?.schema;
|
|
283
|
-
if (schema?.type !== "object") {
|
|
284
|
-
return "";
|
|
285
|
-
}
|
|
286
|
-
const properties = schema.properties;
|
|
287
|
-
if (properties === void 0) {
|
|
288
|
-
return "";
|
|
289
|
-
}
|
|
290
|
-
const propNames = Object.keys(properties);
|
|
291
|
-
return propNames.length > 0 ? `; available properties: ${propNames.join(", ")}` : "";
|
|
292
|
-
}
|
|
293
|
-
function resolveSchemaAtPath(colRef, propertyAccessor, resolvedColumns, ast) {
|
|
294
|
-
const adjustedPath = `$.${propertyAccessor.substring(1).replace(/(\.|\[)/gu, "..properties$1")}`;
|
|
295
|
-
log("adjusted path", adjustedPath);
|
|
296
|
-
const extractedSchemas = resolvedColumns.flatMap(
|
|
297
|
-
(col) => JSONPath({ json: col.schema, path: adjustedPath })
|
|
298
|
-
);
|
|
299
|
-
log("extracted schemas", extractedSchemas);
|
|
300
|
-
if (extractedSchemas.length === 0) {
|
|
301
|
-
throw new AthenaError(
|
|
302
|
-
ATHENA_ERROR,
|
|
303
|
-
`property not found ${colRef} - ${propertyAccessor}${schemaPropertyHint(resolvedColumns)}`,
|
|
304
|
-
ast
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
return extractedSchemas;
|
|
308
|
-
}
|
|
309
|
-
function navigateSchemaPath(colRef, propertyAccessor, resolvedColumns, colName, columnAST, columns) {
|
|
310
|
-
const errorAst = extractJsonExtractCalls(columnAST)[0]?.fnNode ?? columnAST;
|
|
311
|
-
const extractedSchemas = resolveSchemaAtPath(colRef, propertyAccessor, resolvedColumns, errorAst);
|
|
312
|
-
columns.set(
|
|
313
|
-
colName,
|
|
314
|
-
extractedSchemas.map((schema) => resolvedCol(colName, schema, columnAST))
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
function lookupColumnOrThrow(colRef, ref, referencedTables) {
|
|
318
|
-
const resolvedColumns = referencedTables.flatMap((table) => table.columns.get(colRef) ?? []);
|
|
319
|
-
if (resolvedColumns.length === 0) {
|
|
320
|
-
const tableNames = [
|
|
321
|
-
...new Set(referencedTables.map((referenceTable) => referenceTable.name ?? "<anonymous>"))
|
|
322
|
-
].join(", ");
|
|
323
|
-
const availableCols = [...new Set(referencedTables.flatMap((table) => [...table.columns.keys()]))].join(", ");
|
|
324
|
-
throw new AthenaError(
|
|
325
|
-
ATHENA_ERROR,
|
|
326
|
-
`can't found column ${colRef} in tables: ${tableNames}; available columns: ${availableCols}`,
|
|
327
|
-
ref
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
return resolvedColumns;
|
|
331
|
-
}
|
|
332
|
-
function checkColumnRefsExist(ast, allTables, ctx, selectColumns) {
|
|
333
|
-
if (containsLambda(ast)) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
for (const ref of extractColumnRefs(ast)) {
|
|
337
|
-
const colRef = typeof ref.column === "string" ? ref.column : void 0;
|
|
338
|
-
if (colRef === void 0 || colRef === "*") {
|
|
339
|
-
continue;
|
|
340
|
-
}
|
|
341
|
-
const tableRef = ref.table ?? void 0;
|
|
342
|
-
if (tableRef === void 0 && selectColumns?.has(colRef) === true) {
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
345
|
-
const referencedTables = tableRef !== void 0 ? lookupTables(tableRef, ctx) : allTables;
|
|
346
|
-
if (referencedTables.length === 0) {
|
|
347
|
-
throw new AthenaError(
|
|
348
|
-
ATHENA_ERROR,
|
|
349
|
-
`unknown table or alias '${tableRef ?? colRef}'; known tables: ${[...ctx.tables.keys()].join(", ")}`,
|
|
350
|
-
ref
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
lookupColumnOrThrow(colRef, ref, referencedTables);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
function validateComplexColumnExpression(columnAST, allTables, ctx) {
|
|
357
|
-
for (const { ref, path, fnNode } of extractJsonExtractCalls(columnAST)) {
|
|
358
|
-
const tableRef = ref.table ?? void 0;
|
|
359
|
-
const colRef = typeof ref.column === "string" ? ref.column : void 0;
|
|
360
|
-
if (colRef === void 0) {
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
const referencedTables = tableRef !== void 0 ? lookupTables(tableRef, ctx) : allTables;
|
|
364
|
-
const resolvedColumns = referencedTables.flatMap((table) => table.columns.get(colRef) ?? []);
|
|
365
|
-
if (resolvedColumns.length > 0) {
|
|
366
|
-
resolveSchemaAtPath(colRef, path, resolvedColumns, fnNode);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
function resolveSingleColumnRef(columnAST, columnAlias, indexedName, ref, allTables, ctx, columns) {
|
|
371
|
-
const tableRef = ref.table ?? void 0;
|
|
372
|
-
const colRef = typeof ref.column === "string" ? ref.column : void 0;
|
|
373
|
-
assert.ok(colRef !== void 0, "column_ref must have a string column name");
|
|
374
|
-
const referencedTables = tableRef !== void 0 ? lookupTables(tableRef, ctx) : allTables;
|
|
375
|
-
if (referencedTables.length === 0) {
|
|
376
|
-
const tableNames = [...ctx.tables.keys()].join(", ");
|
|
377
|
-
throw new AthenaError(
|
|
378
|
-
ATHENA_ERROR,
|
|
379
|
-
`unknown table or alias '${tableRef ?? colRef}'; known tables: ${tableNames}`,
|
|
380
|
-
ref
|
|
381
|
-
);
|
|
382
|
-
}
|
|
383
|
-
if (colRef === "*") {
|
|
384
|
-
expandWildcard(referencedTables, columns);
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
const withFunctions = hasFunctionCalls(columnAST);
|
|
388
|
-
const colName = columnAlias ?? (withFunctions ? indexedName : colRef);
|
|
389
|
-
const resolvedColumns = lookupColumnOrThrow(colRef, ref, referencedTables);
|
|
390
|
-
const propertyAccessor = extractJsonExtractPath(columnAST) ?? extractBracketAccessorPath(columnAST);
|
|
391
|
-
if (propertyAccessor !== void 0) {
|
|
392
|
-
navigateSchemaPath(colRef, propertyAccessor, resolvedColumns, colName, columnAST, columns);
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
columns.set(
|
|
396
|
-
colName,
|
|
397
|
-
resolvedColumns.map((col) => resolvedCol(colName, col.schema, columnAST))
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
function resolveSelectColumns(select, ctx) {
|
|
401
|
-
const allTables = [...ctx.tables.values()].flat();
|
|
402
|
-
const columns = /* @__PURE__ */ new Map();
|
|
403
|
-
for (const [index, columnAST] of select.columns.entries()) {
|
|
404
|
-
log("resolving column", columnAST);
|
|
405
|
-
const columnAlias = columnAST.as ?? null;
|
|
406
|
-
const indexedName = `_col${String(index)}`;
|
|
407
|
-
const columnRefs = extractColumnRefs(columnAST);
|
|
408
|
-
if (columnRefs.length !== 1) {
|
|
409
|
-
checkColumnRefsExist(columnAST, allTables, ctx);
|
|
410
|
-
validateComplexColumnExpression(columnAST, allTables, ctx);
|
|
411
|
-
resolveDefaultSchemaColumn(columnAlias, indexedName, columnAST, columns);
|
|
412
|
-
} else {
|
|
413
|
-
const [ref] = columnRefs;
|
|
414
|
-
assert.ok(ref !== void 0);
|
|
415
|
-
resolveSingleColumnRef(columnAST, columnAlias, indexedName, ref, allTables, ctx, columns);
|
|
416
|
-
}
|
|
417
|
-
if (containsCastToArray(columnAST)) {
|
|
418
|
-
const colName = columnAlias ?? indexedName;
|
|
419
|
-
const existing = columns.get(colName);
|
|
420
|
-
if (existing !== void 0 && existing[0]?.schema.type !== "array") {
|
|
421
|
-
columns.set(
|
|
422
|
-
colName,
|
|
423
|
-
existing.map((col) => resolvedCol(col.name, { type: "array" }, col.ast))
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
if (containsCastToMap(columnAST)) {
|
|
428
|
-
const colName = columnAlias ?? indexedName;
|
|
429
|
-
const existing = columns.get(colName);
|
|
430
|
-
if (existing !== void 0 && existing[0]?.schema.type !== "object") {
|
|
431
|
-
columns.set(
|
|
432
|
-
colName,
|
|
433
|
-
existing.map((col) => resolvedCol(col.name, { type: "object" }, col.ast))
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
return columns;
|
|
439
|
-
}
|
|
440
|
-
function checkSelect(selectAST, ctx, withTableName) {
|
|
441
|
-
const select = "stmt" in selectAST ? selectAST.stmt.ast : selectAST;
|
|
442
|
-
const selectCtx = createChildContext(ctx);
|
|
443
|
-
resolveFromClause(select, selectCtx);
|
|
444
|
-
restrictToFromClause(select, selectCtx);
|
|
445
|
-
const unnestMappings = extractUnnestMappings(select);
|
|
446
|
-
const deferredUnnest = applyUnnestPre(unnestMappings, selectCtx);
|
|
447
|
-
const columns = resolveSelectColumns(select, selectCtx);
|
|
448
|
-
applyUnnestPost(deferredUnnest, columns);
|
|
449
|
-
log("resolved columns", [...columns.keys()]);
|
|
450
|
-
const allTables = [...selectCtx.tables.values()].flat();
|
|
451
|
-
for (const item of fromClauseItems(select)) {
|
|
452
|
-
const onExpr = item.on;
|
|
453
|
-
if (onExpr !== void 0) {
|
|
454
|
-
checkColumnRefsExist(onExpr, allTables, selectCtx);
|
|
455
|
-
validateComplexColumnExpression(onExpr, allTables, selectCtx);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
if (select.where !== null) {
|
|
459
|
-
checkColumnRefsExist(select.where, allTables, selectCtx);
|
|
460
|
-
validateComplexColumnExpression(select.where, allTables, selectCtx);
|
|
461
|
-
}
|
|
462
|
-
if (select.having !== null) {
|
|
463
|
-
checkColumnRefsExist(select.having, allTables, selectCtx, columns);
|
|
464
|
-
validateComplexColumnExpression(select.having, allTables, selectCtx);
|
|
465
|
-
}
|
|
466
|
-
for (const orderItem of select.orderby ?? []) {
|
|
467
|
-
checkColumnRefsExist(orderItem.expr, allTables, selectCtx, columns);
|
|
468
|
-
validateComplexColumnExpression(orderItem.expr, allTables, selectCtx);
|
|
469
|
-
}
|
|
470
|
-
if (select.groupby?.columns !== void 0) {
|
|
471
|
-
for (const groupCol of select.groupby.columns) {
|
|
472
|
-
checkColumnRefsExist(groupCol, allTables, selectCtx, columns);
|
|
473
|
-
validateComplexColumnExpression(groupCol, allTables, selectCtx);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
if (select._next !== void 0) {
|
|
477
|
-
const nextColumns = checkSelect(select._next, ctx, withTableName);
|
|
478
|
-
const currentNumberOfKeys = columns.size;
|
|
479
|
-
const nextNumberOfKeys = nextColumns.size;
|
|
480
|
-
if (currentNumberOfKeys !== nextNumberOfKeys) {
|
|
481
|
-
throw new AthenaError(
|
|
482
|
-
ATHENA_ERROR,
|
|
483
|
-
`UNION ALL parts have different number of columns: ${currentNumberOfKeys.toString()} vs ${nextNumberOfKeys.toString()}`,
|
|
484
|
-
select._next
|
|
485
|
-
);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
if (withTableName !== void 0) {
|
|
489
|
-
const resolvedTable = { name: withTableName, columns };
|
|
490
|
-
ctx.tables.set(withTableName, [resolvedTable]);
|
|
491
|
-
}
|
|
492
|
-
return columns;
|
|
493
|
-
}
|
|
494
|
-
function checkAthenaAst(ast, ctx) {
|
|
495
|
-
assert.ok(ast.type === "select");
|
|
496
|
-
const select = ast;
|
|
497
|
-
if (select.with !== null) {
|
|
498
|
-
for (const withItem of select.with) {
|
|
499
|
-
checkSelect(withItem.stmt.ast, ctx, withItem.name.value);
|
|
500
|
-
}
|
|
501
|
-
select.with = null;
|
|
502
|
-
}
|
|
503
|
-
checkSelect(select, ctx);
|
|
504
|
-
}
|
|
505
35
|
var rule = createRule({
|
|
506
36
|
name: ruleId,
|
|
507
37
|
meta: {
|
|
@@ -603,4 +133,4 @@ export {
|
|
|
603
133
|
athena_default as default,
|
|
604
134
|
ruleId
|
|
605
135
|
};
|
|
606
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hdGhlbmEudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBVUEsU0FBUyxVQUFVLGNBQWM7QUFFakMsT0FBTyxXQUFXO0FBQ2xCLFNBQVMsZ0JBQWdCO0FBQ3pCLFNBQVMsZ0JBQWdCLG1CQUFrQztBQUczRCxTQUFTLGFBQWE7QUFFdEIsU0FBUyxnQkFBZ0I7QUFDekIsU0FBUyxpQkFBaUI7QUFDMUI7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLE9BSUs7QUFDUCxTQUFTLDBCQUEwQjtBQUNuQztBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLE9BQ0s7QUFFQSxJQUFNLFNBQVM7QUFFdEIsSUFBTSxNQUFNLE1BQU0sc0JBQXNCO0FBQ3hDLElBQU0sYUFBYSxZQUFZLFlBQVksQ0FBQyxTQUFTLElBQUk7QUFFekQsSUFBTSxnQkFBZ0I7QUFDdEIsSUFBTSxlQUFlO0FBRXJCLElBQU0sY0FBTixjQUEwQixNQUFNO0FBQUEsRUFDdkI7QUFBQSxFQUNBO0FBQUEsRUFDUCxZQUFZLE1BQWMsU0FBaUIsS0FBYztBQUN2RCxVQUFNLE9BQU87QUFDYixTQUFLLE9BQU87QUFDWixTQUFLLE9BQU87QUFDWixRQUFJLFFBQVEsUUFBVztBQUNyQixXQUFLLE1BQU07QUFBQSxJQUNiO0FBQUEsRUFDRjtBQUNGO0FBR0EsU0FBUyxZQUFZLE1BQWMsUUFBa0Q7QUFDbkYsUUFBTSxTQUFTLEtBQUssTUFBTSxHQUFHLE1BQU07QUFDbkMsUUFBTSxRQUFRLE9BQU8sTUFBTSxJQUFJO0FBQy9CLFNBQU8sRUFBRSxNQUFNLE1BQU0sUUFBUSxRQUFRLE1BQU0sTUFBTSxTQUFTLENBQUMsR0FBRyxVQUFVLEVBQUU7QUFDNUU7QUFXQSxTQUFTLGdCQUFnQixTQUE0QztBQUNu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
|
|
136
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9hdGhlbmEudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBUUEsT0FBTyxXQUFXO0FBQ2xCLFNBQVMsZ0JBQWdCLG1CQUFrQztBQUUzRCxTQUFTLGFBQWE7QUFFdEIsU0FBUyx5QkFBeUI7QUFDbEMsU0FBUyxjQUFjLGFBQWEsZ0JBQWdCLGFBQWEscUJBQXFCO0FBRS9FLElBQU0sU0FBUztBQUV0QixJQUFNLE1BQU0sTUFBTSxzQkFBc0I7QUFDeEMsSUFBTSxhQUFhLFlBQVksWUFBWSxDQUFDLFNBQVMsSUFBSTtBQVd6RCxTQUFTLGdCQUFnQixTQUE0QztBQUNuRSxNQUFJLFFBQVEsU0FBUyxlQUFlLGlCQUFpQjtBQUVuRCxXQUFPLENBQUMsRUFBRSxVQUFVLEdBQUcsVUFBVSxRQUFRLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUFBLEVBQ3pEO0FBQ0EsUUFBTSxTQUFTLFFBQVEsT0FBTyxJQUFJLENBQUMsVUFBVSxNQUFNLE1BQU0sVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFO0FBQzlFLFFBQU0sWUFBWSxPQUFPLFNBQVMsT0FBTyxVQUFVLEVBQUU7QUFDckQsUUFBTSxXQUErQixDQUFDO0FBQ3RDLE1BQUksWUFBWTtBQUNoQixhQUFXLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxPQUFPLFFBQVEsR0FBRztBQUNyRCxVQUFNLFNBQVMsTUFBTSxNQUFNLFVBQVU7QUFDckMsVUFBTSxZQUFZLFVBQVUsSUFBSSxZQUFZO0FBRTVDLGFBQVMsS0FBSyxFQUFFLFVBQVUsV0FBVyxVQUFVLE1BQU0sTUFBTSxDQUFDLElBQUksSUFBSSxVQUFVLENBQUM7QUFDL0UsaUJBQWEsT0FBTyxTQUFTO0FBQUEsRUFDL0I7QUFDQSxTQUFPO0FBQ1Q7QUFFQSxTQUFTLGtCQUFrQixXQUFtQixVQUFzQztBQUNsRixXQUFTLFFBQVEsU0FBUyxTQUFTLEdBQUcsU0FBUyxHQUFHLFNBQVM7QUFDekQsVUFBTSxNQUFNLFNBQVMsS0FBSztB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
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// src/athena/sql-file.ts
|
|
2
|
+
import debug from "debug";
|
|
3
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
4
|
+
import { parse } from "../peggy/athena-peggy.mjs";
|
|
5
|
+
import { createRootContext } from "./context.mjs";
|
|
6
|
+
import { ATHENA_ERROR, AthenaError, checkAthenaAst, offsetToLoc, SYNTEXT_ERROR } from "./validate.mjs";
|
|
7
|
+
var ruleId = "sql-file";
|
|
8
|
+
var log = debug("eslint-plugin:sql-file");
|
|
9
|
+
var createRule = ESLintUtils.RuleCreator((name) => name);
|
|
10
|
+
var rule = createRule({
|
|
11
|
+
name: ruleId,
|
|
12
|
+
meta: {
|
|
13
|
+
type: "problem",
|
|
14
|
+
docs: {
|
|
15
|
+
description: "Validate plain .sql files against OpenAPI schemas at lint time"
|
|
16
|
+
},
|
|
17
|
+
schema: [],
|
|
18
|
+
messages: {
|
|
19
|
+
[SYNTEXT_ERROR]: `SyntextError {{ errorMessage }}`,
|
|
20
|
+
[ATHENA_ERROR]: `AthenaError {{ errorMessage }}`
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: [],
|
|
24
|
+
create(context) {
|
|
25
|
+
return {
|
|
26
|
+
// Program fires once per file; the entire source text is the SQL to validate.
|
|
27
|
+
Program() {
|
|
28
|
+
const sql = context.sourceCode.getText();
|
|
29
|
+
if (!/^\s*(?:SELECT\b[\s\S]*\bFROM\b|WITH\b[\s\S]*\bSELECT\b[\s\S]*\b)/iu.test(sql)) {
|
|
30
|
+
log("skipping non-SELECT SQL", { filename: context.filename });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
let ast;
|
|
34
|
+
try {
|
|
35
|
+
({ ast } = parse(sql, { includeLocations: true }));
|
|
36
|
+
} catch (error) {
|
|
37
|
+
log("error parsing SQL", { error, filename: context.filename });
|
|
38
|
+
const pegLoc = error.location;
|
|
39
|
+
if (pegLoc !== void 0) {
|
|
40
|
+
context.report({
|
|
41
|
+
loc: {
|
|
42
|
+
start: offsetToLoc(sql, pegLoc.start.offset),
|
|
43
|
+
end: offsetToLoc(sql, pegLoc.end.offset)
|
|
44
|
+
},
|
|
45
|
+
messageId: SYNTEXT_ERROR,
|
|
46
|
+
data: { errorMessage: error.message }
|
|
47
|
+
});
|
|
48
|
+
} else {
|
|
49
|
+
context.report({
|
|
50
|
+
loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
51
|
+
messageId: SYNTEXT_ERROR,
|
|
52
|
+
data: { errorMessage: error.message }
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const athenaCtx = createRootContext();
|
|
58
|
+
try {
|
|
59
|
+
checkAthenaAst(Array.isArray(ast) ? ast[0] : ast, athenaCtx);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
log("error checking SQL AST", { error, filename: context.filename });
|
|
62
|
+
if (error instanceof AthenaError) {
|
|
63
|
+
const astLoc = error.ast?.loc;
|
|
64
|
+
if (astLoc !== void 0) {
|
|
65
|
+
context.report({
|
|
66
|
+
loc: {
|
|
67
|
+
start: offsetToLoc(sql, astLoc.start.offset),
|
|
68
|
+
end: offsetToLoc(sql, astLoc.end.offset)
|
|
69
|
+
},
|
|
70
|
+
messageId: ATHENA_ERROR,
|
|
71
|
+
data: { errorMessage: error.message }
|
|
72
|
+
});
|
|
73
|
+
} else {
|
|
74
|
+
context.report({
|
|
75
|
+
loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
76
|
+
messageId: ATHENA_ERROR,
|
|
77
|
+
data: { errorMessage: error.message }
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
console.error(`Failed to apply ${ruleId} rule for "${context.filename}":`, error);
|
|
82
|
+
context.report({
|
|
83
|
+
loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
84
|
+
messageId: ATHENA_ERROR,
|
|
85
|
+
data: {
|
|
86
|
+
errorMessage: error instanceof Error ? String(error) : JSON.stringify(error, void 0, 2)
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
var sql_file_default = rule;
|
|
96
|
+
export {
|
|
97
|
+
sql_file_default as default,
|
|
98
|
+
ruleId
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2F0aGVuYS9zcWwtZmlsZS50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFRQSxPQUFPLFdBQVc7QUFDbEIsU0FBUyxtQkFBbUI7QUFFNUIsU0FBUyxhQUFhO0FBRXRCLFNBQVMseUJBQXlCO0FBQ2xDLFNBQVMsY0FBYyxhQUFhLGdCQUFnQixhQUFhLHFCQUFxQjtBQUUvRSxJQUFNLFNBQVM7QUFFdEIsSUFBTSxNQUFNLE1BQU0sd0JBQXdCO0FBQzFDLElBQU0sYUFBYSxZQUFZLFlBQVksQ0FBQyxTQUFTLElBQUk7QUFFekQsSUFBTSxPQUEyRSxXQUFXO0FBQUEsRUFDMUYsTUFBTTtBQUFBLEVBQ04sTUFBTTtBQUFBLElBQ0osTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLE1BQ0osYUFBYTtBQUFBLElBQ2Y7QUFBQSxJQUNBLFFBQVEsQ0FBQztBQUFBLElBQ1QsVUFBVTtBQUFBLE1BQ1IsQ0FBQyxhQUFhLEdBQUc7QUFBQSxNQUNqQixDQUFDLFlBQVksR0FBRztBQUFBLElBQ2xCO0FBQUEsRUFDRjtBQUFBLEVBQ0EsZ0JBQWdCLENBQUM7QUFBQSxFQUNqQixPQUFPLFNBQVM7QUFDZCxXQUFPO0FBQUE7QUFBQSxNQUVMLFVBQVU7QUFDUixjQUFNLE1BQU0sUUFBUSxXQUFXLFFBQVE7QUFFdkMsWUFBSSxDQUFDLHFFQUFxRSxLQUFLLEdBQUcsR0FBRztBQUNuRixjQUFJLDJCQUEyQixFQUFFLFVBQVUsUUFBUSxTQUFTLENBQUM7QUFDN0Q7QUFBQSxRQUNGO0FBRUEsWUFBSTtBQUNKLFlBQUk7QUFFRixXQUFDLEVBQUUsSUFBSSxJQUFJLE1BQU0sS0FBSyxFQUFFLGtCQUFrQixLQUFLLENBQUM7QUFBQSxRQUNsRCxTQUFTLE9BQU87QUFDZCxjQUFJLHFCQUFxQixFQUFFLE9BQU8sVUFBVSxRQUFRLFNBQVMsQ0FBQztBQUM5RCxnQkFBTSxTQUFVLE1BQWdGO0FBQ2hHLGNBQUksV0FBVyxRQUFXO0FBRXhCLG9CQUFRLE9BQU87QUFBQSxjQUNiLEtBQUs7QUFBQSxnQkFDSCxPQUFPLFlBQVksS0FBSyxPQUFPLE1BQU0sTUFBTTtBQUFBLGdCQUMzQyxLQUFLLFlBQVksS0FBSyxPQUFPLElBQUksTUFBTTtBQUFBLGNBQ3pDO0FBQUEsY0FDQSxXQUFXO0FBQUEsY0FDWCxNQUFNLEVBQUUsY0FBZSxNQUFnQixRQUFRO0FBQUEsWUFDakQsQ0FBQztBQUFBLFVBQ0gsT0FBTztBQUNMLG9CQUFRLE9BQU87QUFBQSxjQUNiLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxHQUFHLFFBQVEsRUFBRSxHQUFHLEtBQUssRUFBRSxNQUFNLEdBQUcsUUFBUSxFQUFFLEVBQUU7QUFBQSxjQUNsRSxXQUFXO0FBQUEsY0FDWCxNQUFNLEVBQUUsY0FBZSxNQUFnQixRQUFRO0FBQUEsWUFDakQsQ0FBQztBQUFBLFVBQ0g7QUFDQTtBQUFBLFFBQ0Y7QUFFQSxjQUFNLFlBQVksa0JBQWtCO0FBQ3BDLFlBQUk7QUFFRix5QkFBZSxNQUFNLFFBQVEsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssU0FBUztBQUFBLFFBQzdELFNBQVMsT0FBTztBQUNkLGNBQUksMEJBQTBCLEVBQUUsT0FBTyxVQUFVLFFBQVEsU0FBUyxDQUFDO0FBQ25FLGNBQUksaUJBQWlCLGFBQWE7QUFDaEMsa0JBQU0sU0FBVSxNQUFNLEtBQ2xCO0FBQ0osZ0JBQUksV0FBVyxRQUFXO0FBQ3hCLHNCQUFRLE9BQU87QUFBQSxnQkFDYixLQUFLO0FBQUEsa0JBQ0gsT0FBTyxZQUFZLEtBQUssT0FBTyxNQUFNLE1BQU07QUFBQSxrQkFDM0MsS0FBSyxZQUFZLEtBQUssT0FBTyxJQUFJLE1BQU07QUFBQSxnQkFDekM7QUFBQSxnQkFDQSxXQUFXO0FBQUEsZ0JBQ1gsTUFBTSxFQUFFLGNBQWMsTUFBTSxRQUFRO0FBQUEsY0FDdEMsQ0FBQztBQUFBLFlBQ0gsT0FBTztBQUNMLHNCQUFRLE9BQU87QUFBQSxnQkFDYixLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sR0FBRyxRQUFRLEVBQUUsR0FBRyxLQUFLLEVBQUUsTUFBTSxHQUFHLFFBQVEsRUFBRSxFQUFFO0FBQUEsZ0JBQ2xFLFdBQVc7QUFBQSxnQkFDWCxNQUFNLEVBQUUsY0FBYyxNQUFNLFFBQVE7QUFBQSxjQUN0QyxDQUFDO0FBQUEsWUFDSDtBQUFBLFVBQ0YsT0FBTztBQUVMLG9CQUFRLE1BQU0sbUJBQW1CLE1BQU0sY0FBYyxRQUFRLFFBQVEsTUFBTSxLQUFLO0FBQ2hGLG9CQUFRLE9BQU87QUFBQSxjQUNiLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxHQUFHLFFBQVEsRUFBRSxHQUFHLEtBQUssRUFBRSxNQUFNLEdBQUcsUUFBUSxFQUFFLEVBQUU7QUFBQSxjQUNsRSxXQUFXO0FBQUEsY0FDWCxNQUFNO0FBQUEsZ0JBQ0osY0FBYyxpQkFBaUIsUUFBUSxPQUFPLEtBQUssSUFBSSxLQUFLLFVBQVUsT0FBTyxRQUFXLENBQUM7QUFBQSxjQUMzRjtBQUFBLFlBQ0YsQ0FBQztBQUFBLFVBQ0g7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQztBQUVELElBQU8sbUJBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==
|