eslint-plugin-slonik 1.7.0 → 1.8.0
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/index.cjs +13 -392
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +10 -389
- package/dist/index.mjs.map +1 -1
- package/dist/shared/{eslint-plugin-slonik.DwYTOoDn.mjs → eslint-plugin-slonik.CHihwTq0.mjs} +3 -176
- package/dist/shared/eslint-plugin-slonik.CHihwTq0.mjs.map +1 -0
- package/dist/shared/{eslint-plugin-slonik.rlOTrCdf.cjs → eslint-plugin-slonik.kniz1QWh.cjs} +2 -184
- package/dist/shared/eslint-plugin-slonik.kniz1QWh.cjs.map +1 -0
- package/dist/workers/check-sql.worker.cjs +1 -2
- package/dist/workers/check-sql.worker.cjs.map +1 -1
- package/dist/workers/check-sql.worker.mjs +1 -2
- package/dist/workers/check-sql.worker.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/shared/eslint-plugin-slonik.DwYTOoDn.mjs.map +0 -1
- package/dist/shared/eslint-plugin-slonik.rlOTrCdf.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const checkSql_utils = require('./shared/eslint-plugin-slonik.
|
|
3
|
+
const checkSql_utils = require('./shared/eslint-plugin-slonik.kniz1QWh.cjs');
|
|
4
4
|
const utils = require('@typescript-eslint/utils');
|
|
5
5
|
const tsPattern = require('ts-pattern');
|
|
6
6
|
const E = require('fp-ts/lib/Either.js');
|
|
@@ -8,9 +8,9 @@ const function_js = require('fp-ts/lib/function.js');
|
|
|
8
8
|
require('fp-ts/lib/Option.js');
|
|
9
9
|
require('fp-ts/lib/TaskEither.js');
|
|
10
10
|
const J = require('fp-ts/lib/Json.js');
|
|
11
|
-
const ts = require('typescript');
|
|
12
11
|
const path = require('path');
|
|
13
12
|
const fs = require('fs');
|
|
13
|
+
const ts = require('typescript');
|
|
14
14
|
const synckit = require('synckit');
|
|
15
15
|
const node_url = require('node:url');
|
|
16
16
|
const z = require('zod');
|
|
@@ -35,226 +35,16 @@ function _interopNamespaceCompat(e) {
|
|
|
35
35
|
|
|
36
36
|
const E__namespace = /*#__PURE__*/_interopNamespaceCompat(E);
|
|
37
37
|
const J__namespace = /*#__PURE__*/_interopNamespaceCompat(J);
|
|
38
|
-
const ts__default = /*#__PURE__*/_interopDefaultCompat(ts);
|
|
39
38
|
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
40
39
|
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
40
|
+
const ts__default = /*#__PURE__*/_interopDefaultCompat(ts);
|
|
41
41
|
const z__default = /*#__PURE__*/_interopDefaultCompat(z);
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
number: "number",
|
|
46
|
-
boolean: "boolean",
|
|
47
|
-
false: "false",
|
|
48
|
-
true: "true",
|
|
49
|
-
null: "null",
|
|
50
|
-
undefined: "undefined",
|
|
51
|
-
any: "any"
|
|
52
|
-
};
|
|
53
|
-
function getResolvedTargetByTypeNode(params) {
|
|
54
|
-
if (!params.typeNode) {
|
|
55
|
-
console.error("[slonik/check-sql] DEBUG: typeNode is undefined in getResolvedTargetByTypeNode");
|
|
56
|
-
throw new Error("typeNode is undefined");
|
|
57
|
-
}
|
|
58
|
-
const tsNode = params.parser.esTreeNodeToTSNodeMap.get(params.typeNode);
|
|
59
|
-
if (!tsNode) {
|
|
60
|
-
console.error("[slonik/check-sql] DEBUG: Could not map ESTree node to TS node. typeNode.type:", params.typeNode.type);
|
|
61
|
-
throw new Error(`Could not map ESTree node (type: ${params.typeNode.type}) to TS node`);
|
|
62
|
-
}
|
|
63
|
-
const typeText = tsNode.getText();
|
|
64
|
-
if (isReservedType(typeText, params.reservedTypes)) {
|
|
65
|
-
return { kind: "type", value: typeText };
|
|
66
|
-
}
|
|
67
|
-
switch (params.typeNode.type) {
|
|
68
|
-
case utils.TSESTree.AST_NODE_TYPES.TSLiteralType:
|
|
69
|
-
return handleLiteralType(params.typeNode);
|
|
70
|
-
case utils.TSESTree.AST_NODE_TYPES.TSUnionType:
|
|
71
|
-
return {
|
|
72
|
-
kind: "union",
|
|
73
|
-
value: params.typeNode.types.map(
|
|
74
|
-
(type) => getResolvedTargetByTypeNode({ ...params, typeNode: type })
|
|
75
|
-
)
|
|
76
|
-
};
|
|
77
|
-
case utils.TSESTree.AST_NODE_TYPES.TSNullKeyword:
|
|
78
|
-
return { kind: "type", value: "null" };
|
|
79
|
-
case utils.TSESTree.AST_NODE_TYPES.TSUndefinedKeyword:
|
|
80
|
-
return { kind: "type", value: "undefined" };
|
|
81
|
-
case utils.TSESTree.AST_NODE_TYPES.TSTypeLiteral:
|
|
82
|
-
return handleTypeLiteral(params.typeNode, params);
|
|
83
|
-
case utils.TSESTree.AST_NODE_TYPES.TSTypeReference:
|
|
84
|
-
return handleTypeReference(params.typeNode, params);
|
|
85
|
-
case utils.TSESTree.AST_NODE_TYPES.TSIntersectionType:
|
|
86
|
-
return handleIntersectionType(params.typeNode, params);
|
|
87
|
-
case utils.TSESTree.AST_NODE_TYPES.TSArrayType:
|
|
88
|
-
return {
|
|
89
|
-
kind: "array",
|
|
90
|
-
value: getResolvedTargetByTypeNode({
|
|
91
|
-
...params,
|
|
92
|
-
typeNode: params.typeNode.elementType
|
|
93
|
-
})
|
|
94
|
-
};
|
|
95
|
-
default:
|
|
96
|
-
return { kind: "type", value: typeText };
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function isReservedType(typeText, reservedTypes) {
|
|
100
|
-
return reservedTypes.has(typeText) || reservedTypes.has(`${typeText}[]`);
|
|
101
|
-
}
|
|
102
|
-
function handleLiteralType(typeNode) {
|
|
103
|
-
return typeNode.literal.type === utils.TSESTree.AST_NODE_TYPES.Literal ? { kind: "type", value: `'${typeNode.literal.value}'` } : { kind: "type", value: "unknown" };
|
|
104
|
-
}
|
|
105
|
-
function handleTypeLiteral(typeNode, params) {
|
|
106
|
-
const properties = typeNode.members.flatMap((member) => {
|
|
107
|
-
if (member.type !== utils.TSESTree.AST_NODE_TYPES.TSPropertySignature || !member.typeAnnotation) {
|
|
108
|
-
return [];
|
|
109
|
-
}
|
|
110
|
-
const key = extractPropertyKey(member.key);
|
|
111
|
-
if (!key) return [];
|
|
112
|
-
const propertyName = member.optional ? `${key}?` : key;
|
|
113
|
-
const propertyType = getResolvedTargetByTypeNode({
|
|
114
|
-
...params,
|
|
115
|
-
typeNode: member.typeAnnotation.typeAnnotation
|
|
116
|
-
});
|
|
117
|
-
return [[propertyName, propertyType]];
|
|
118
|
-
});
|
|
119
|
-
return { kind: "object", value: properties };
|
|
120
|
-
}
|
|
121
|
-
function extractPropertyKey(key) {
|
|
122
|
-
switch (key.type) {
|
|
123
|
-
case utils.TSESTree.AST_NODE_TYPES.Identifier:
|
|
124
|
-
return key.name;
|
|
125
|
-
case utils.TSESTree.AST_NODE_TYPES.Literal:
|
|
126
|
-
return String(key.value);
|
|
127
|
-
default:
|
|
128
|
-
return void 0;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
function handleTypeReference(typeNode, params) {
|
|
132
|
-
if (typeNode.typeName.type !== utils.TSESTree.AST_NODE_TYPES.Identifier && typeNode.typeName.type !== utils.TSESTree.AST_NODE_TYPES.TSQualifiedName) {
|
|
133
|
-
return { kind: "type", value: "unknown" };
|
|
134
|
-
}
|
|
135
|
-
const typeNameText = params.parser.esTreeNodeToTSNodeMap.get(typeNode.typeName).getText();
|
|
136
|
-
if (params.reservedTypes.has(typeNameText)) {
|
|
137
|
-
return { kind: "type", value: typeNameText };
|
|
138
|
-
}
|
|
139
|
-
if (typeNameText === "Array" && typeNode.typeArguments?.params[0]) {
|
|
140
|
-
return {
|
|
141
|
-
kind: "array",
|
|
142
|
-
syntax: "type-reference",
|
|
143
|
-
value: getResolvedTargetByTypeNode({
|
|
144
|
-
...params,
|
|
145
|
-
typeNode: typeNode.typeArguments.params[0]
|
|
146
|
-
})
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
const type = params.checker.getTypeFromTypeNode(
|
|
150
|
-
params.parser.esTreeNodeToTSNodeMap.get(typeNode)
|
|
151
|
-
);
|
|
152
|
-
return resolveType(type, { ...params, typeNode });
|
|
153
|
-
}
|
|
154
|
-
function handleIntersectionType(typeNode, params) {
|
|
155
|
-
const allProperties = typeNode.types.flatMap((type) => {
|
|
156
|
-
const resolved = getResolvedTargetByTypeNode({ ...params, typeNode: type });
|
|
157
|
-
return resolved.kind === "object" ? resolved.value : [];
|
|
158
|
-
});
|
|
159
|
-
return { kind: "object", value: Array.from(new Map(allProperties).entries()) };
|
|
160
|
-
}
|
|
161
|
-
function resolveType(type, params) {
|
|
162
|
-
const typeAsString = params.checker.typeToString(type);
|
|
163
|
-
if (params.reservedTypes.has(typeAsString)) {
|
|
164
|
-
return { kind: "type", value: typeAsString };
|
|
165
|
-
}
|
|
166
|
-
if (params.reservedTypes.has(`${typeAsString}[]`)) {
|
|
167
|
-
return { kind: "array", value: { kind: "type", value: typeAsString.replace("[]", "") } };
|
|
168
|
-
}
|
|
169
|
-
const primitive = getPrimitiveType(type, typeAsString);
|
|
170
|
-
if (primitive) return primitive;
|
|
171
|
-
if (type.isLiteral()) {
|
|
172
|
-
return { kind: "type", value: `'${type.value}'` };
|
|
173
|
-
}
|
|
174
|
-
if (type.isUnion()) {
|
|
175
|
-
return handleUnionTypeReference(type, params);
|
|
176
|
-
}
|
|
177
|
-
if (type.isIntersection()) {
|
|
178
|
-
return handleIntersectionTypeReference(type, params);
|
|
179
|
-
}
|
|
180
|
-
if (params.checker.isArrayType(type)) {
|
|
181
|
-
return handleArrayTypeReferenceFromType(type, params);
|
|
182
|
-
}
|
|
183
|
-
return handleObjectType(type, params);
|
|
184
|
-
}
|
|
185
|
-
function getPrimitiveType(type, typeAsString) {
|
|
186
|
-
if (PRIMITIVES[typeAsString]) {
|
|
187
|
-
return { kind: "type", value: PRIMITIVES[typeAsString] };
|
|
188
|
-
}
|
|
189
|
-
const flagMap = {
|
|
190
|
-
[ts__default.TypeFlags.String]: "string",
|
|
191
|
-
[ts__default.TypeFlags.Number]: "number",
|
|
192
|
-
[ts__default.TypeFlags.Boolean]: "boolean",
|
|
193
|
-
[ts__default.TypeFlags.Null]: "null",
|
|
194
|
-
[ts__default.TypeFlags.Undefined]: "undefined",
|
|
195
|
-
[ts__default.TypeFlags.Any]: "any"
|
|
196
|
-
};
|
|
197
|
-
return flagMap[type.flags] ? { kind: "type", value: flagMap[type.flags] } : null;
|
|
43
|
+
function isIdentifier(node) {
|
|
44
|
+
return node?.type === utils.TSESTree.AST_NODE_TYPES.Identifier;
|
|
198
45
|
}
|
|
199
|
-
function
|
|
200
|
-
|
|
201
|
-
const isBooleanUnionWithNull = types.length === 3 && types.some((t) => t.value === "false") && types.some((t) => t.value === "true") && types.some((t) => t.value === "null");
|
|
202
|
-
if (isBooleanUnionWithNull) {
|
|
203
|
-
return {
|
|
204
|
-
kind: "union",
|
|
205
|
-
value: [
|
|
206
|
-
{ kind: "type", value: "boolean" },
|
|
207
|
-
{ kind: "type", value: "null" }
|
|
208
|
-
]
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
return { kind: "union", value: types };
|
|
212
|
-
}
|
|
213
|
-
function handleIntersectionTypeReference(type, params) {
|
|
214
|
-
const properties = type.types.flatMap((t) => {
|
|
215
|
-
const resolved = resolveType(t, params);
|
|
216
|
-
return resolved.kind === "object" ? resolved.value : [];
|
|
217
|
-
});
|
|
218
|
-
return { kind: "object", value: properties };
|
|
219
|
-
}
|
|
220
|
-
function handleArrayTypeReferenceFromType(type, params) {
|
|
221
|
-
const typeArguments = type.typeArguments;
|
|
222
|
-
const firstArgument = typeArguments?.[0];
|
|
223
|
-
if (firstArgument) {
|
|
224
|
-
const elementType = resolveType(firstArgument, params);
|
|
225
|
-
return { kind: "array", value: elementType };
|
|
226
|
-
}
|
|
227
|
-
return { kind: "array", value: { kind: "type", value: "unknown" } };
|
|
228
|
-
}
|
|
229
|
-
function handleObjectType(type, params) {
|
|
230
|
-
if (!type.symbol) {
|
|
231
|
-
return { kind: "type", value: type.aliasSymbol?.escapedName.toString() ?? "unknown" };
|
|
232
|
-
}
|
|
233
|
-
if (type.symbol.valueDeclaration) {
|
|
234
|
-
const declaration = type.symbol.valueDeclaration;
|
|
235
|
-
const sourceFile = declaration.getSourceFile();
|
|
236
|
-
const filePath = sourceFile.fileName;
|
|
237
|
-
if (!filePath.includes("node_modules")) {
|
|
238
|
-
return extractObjectProperties(type, params);
|
|
239
|
-
}
|
|
240
|
-
return { kind: "type", value: type.symbol.name };
|
|
241
|
-
}
|
|
242
|
-
if (type.flags === ts__default.TypeFlags.Object) {
|
|
243
|
-
return extractObjectProperties(type, params);
|
|
244
|
-
}
|
|
245
|
-
return { kind: "object", value: [] };
|
|
246
|
-
}
|
|
247
|
-
function extractObjectProperties(type, params) {
|
|
248
|
-
const properties = type.getProperties().map((property) => {
|
|
249
|
-
const key = property.escapedName.toString();
|
|
250
|
-
const propType = params.checker.getTypeOfSymbolAtLocation(
|
|
251
|
-
property,
|
|
252
|
-
params.parser.esTreeNodeToTSNodeMap.get(params.typeNode)
|
|
253
|
-
);
|
|
254
|
-
const resolvedType = resolveType(propType, params);
|
|
255
|
-
return [key, resolvedType];
|
|
256
|
-
});
|
|
257
|
-
return { kind: "object", value: properties };
|
|
46
|
+
function isMemberExpression(node) {
|
|
47
|
+
return node?.type === utils.TSESTree.AST_NODE_TYPES.MemberExpression;
|
|
258
48
|
}
|
|
259
49
|
|
|
260
50
|
function isInEditorEnv() {
|
|
@@ -1189,7 +979,6 @@ const zConfig = z__default.object({
|
|
|
1189
979
|
connections: z__default.union([z__default.array(zRuleOptionConnection), zRuleOptionConnection])
|
|
1190
980
|
});
|
|
1191
981
|
const RuleOptions = z__default.array(zConfig).min(1).max(1);
|
|
1192
|
-
const defaultInferLiteralOptions = ["string"];
|
|
1193
982
|
|
|
1194
983
|
function getConfigFromFileWithContext(params) {
|
|
1195
984
|
return params.context.options[0];
|
|
@@ -1198,12 +987,7 @@ function getConfigFromFileWithContext(params) {
|
|
|
1198
987
|
const messages = {
|
|
1199
988
|
typeInferenceFailed: "Type inference failed {{error}}",
|
|
1200
989
|
error: "{{error}}",
|
|
1201
|
-
invalidQuery: "Invalid Query: {{error}}"
|
|
1202
|
-
missingTypeAnnotations: "Query is missing type annotation\n Fix with: {{fix}}",
|
|
1203
|
-
incorrectTypeAnnotations: `Query has incorrect type annotation.
|
|
1204
|
-
Expected: {{expected}}
|
|
1205
|
-
Actual: {{actual}}`,
|
|
1206
|
-
invalidTypeAnnotations: `Query has invalid type annotation (SafeQL does not support it. If you think it should, please open an issue)`
|
|
990
|
+
invalidQuery: "Invalid Query: {{error}}"
|
|
1207
991
|
};
|
|
1208
992
|
function check(params) {
|
|
1209
993
|
const connections = Array.isArray(params.config.connections) ? params.config.connections : [params.config.connections];
|
|
@@ -1214,10 +998,10 @@ function check(params) {
|
|
|
1214
998
|
}
|
|
1215
999
|
}
|
|
1216
1000
|
function isTagMemberValid(expr) {
|
|
1217
|
-
if (
|
|
1001
|
+
if (isIdentifier(expr.tag)) {
|
|
1218
1002
|
return true;
|
|
1219
1003
|
}
|
|
1220
|
-
if (
|
|
1004
|
+
if (isMemberExpression(expr.tag) && isIdentifier(expr.tag.property)) {
|
|
1221
1005
|
return true;
|
|
1222
1006
|
}
|
|
1223
1007
|
return false;
|
|
@@ -1239,13 +1023,11 @@ const generateSyncE = function_js.flow(
|
|
|
1239
1023
|
);
|
|
1240
1024
|
let fatalError;
|
|
1241
1025
|
function reportCheck(params) {
|
|
1242
|
-
const { context, tag, connection, target, projectDir
|
|
1026
|
+
const { context, tag, connection, target, projectDir } = params;
|
|
1243
1027
|
if (fatalError !== void 0) {
|
|
1244
1028
|
const hint = isInEditorEnv() ? "If you think this is a bug, please open an issue. If not, please try to fix the error and restart ESLint." : "If you think this is a bug, please open an issue.";
|
|
1245
1029
|
return checkSql_utils.reportBaseError({ context, error: fatalError, tag, hint });
|
|
1246
1030
|
}
|
|
1247
|
-
const nullAsOptional = connection.nullAsOptional ?? false;
|
|
1248
|
-
const nullAsUndefined = connection.nullAsUndefined ?? false;
|
|
1249
1031
|
return function_js.pipe(
|
|
1250
1032
|
E__namespace.Do,
|
|
1251
1033
|
E__namespace.bind("parser", () => {
|
|
@@ -1309,83 +1091,7 @@ If you believe this query should be supported, please open an issue at https://g
|
|
|
1309
1091
|
return;
|
|
1310
1092
|
}).exhaustive();
|
|
1311
1093
|
},
|
|
1312
|
-
(
|
|
1313
|
-
if (result === null) {
|
|
1314
|
-
return;
|
|
1315
|
-
}
|
|
1316
|
-
const isMissingTypeAnnotations = typeParameter === void 0;
|
|
1317
|
-
if (isMissingTypeAnnotations) {
|
|
1318
|
-
if (result.output === null) {
|
|
1319
|
-
return;
|
|
1320
|
-
}
|
|
1321
|
-
return checkSql_utils.reportMissingTypeAnnotations({
|
|
1322
|
-
tag,
|
|
1323
|
-
context,
|
|
1324
|
-
baseNode,
|
|
1325
|
-
actual: checkSql_utils.getFinalResolvedTargetString({
|
|
1326
|
-
target: result.output,
|
|
1327
|
-
nullAsOptional: nullAsOptional ?? false,
|
|
1328
|
-
nullAsUndefined: nullAsUndefined ?? false,
|
|
1329
|
-
transform: target.transform,
|
|
1330
|
-
inferLiterals: connection.inferLiterals ?? defaultInferLiteralOptions
|
|
1331
|
-
})
|
|
1332
|
-
});
|
|
1333
|
-
}
|
|
1334
|
-
const reservedTypes = memoize({
|
|
1335
|
-
key: `reserved-types:${JSON.stringify(connection.overrides)}`,
|
|
1336
|
-
value: () => {
|
|
1337
|
-
const types = /* @__PURE__ */ new Set();
|
|
1338
|
-
for (const value of Object.values(connection.overrides?.types ?? {})) {
|
|
1339
|
-
types.add(typeof value === "string" ? value : value.return);
|
|
1340
|
-
}
|
|
1341
|
-
for (const columnType of Object.values(connection.overrides?.columns ?? {})) {
|
|
1342
|
-
types.add(columnType);
|
|
1343
|
-
}
|
|
1344
|
-
return types;
|
|
1345
|
-
}
|
|
1346
|
-
});
|
|
1347
|
-
const typeAnnotationState = getTypeAnnotationState({
|
|
1348
|
-
generated: result.output,
|
|
1349
|
-
typeParameter,
|
|
1350
|
-
transform: target.transform,
|
|
1351
|
-
checker,
|
|
1352
|
-
parser,
|
|
1353
|
-
reservedTypes,
|
|
1354
|
-
nullAsOptional,
|
|
1355
|
-
nullAsUndefined,
|
|
1356
|
-
inferLiterals: connection.inferLiterals ?? defaultInferLiteralOptions
|
|
1357
|
-
});
|
|
1358
|
-
if (typeAnnotationState === "INVALID") {
|
|
1359
|
-
return checkSql_utils.reportInvalidTypeAnnotations({
|
|
1360
|
-
context,
|
|
1361
|
-
typeParameter
|
|
1362
|
-
});
|
|
1363
|
-
}
|
|
1364
|
-
if (!typeAnnotationState.isEqual) {
|
|
1365
|
-
return checkSql_utils.reportIncorrectTypeAnnotations({
|
|
1366
|
-
context,
|
|
1367
|
-
typeParameter,
|
|
1368
|
-
expected: checkSql_utils.fmap(
|
|
1369
|
-
typeAnnotationState.expected,
|
|
1370
|
-
(expected) => checkSql_utils.getResolvedTargetString({
|
|
1371
|
-
target: expected,
|
|
1372
|
-
nullAsOptional: false,
|
|
1373
|
-
nullAsUndefined: false,
|
|
1374
|
-
inferLiterals: params.connection.inferLiterals ?? defaultInferLiteralOptions
|
|
1375
|
-
})
|
|
1376
|
-
),
|
|
1377
|
-
actual: checkSql_utils.fmap(
|
|
1378
|
-
result.output,
|
|
1379
|
-
(output) => checkSql_utils.getFinalResolvedTargetString({
|
|
1380
|
-
target: output,
|
|
1381
|
-
nullAsOptional: connection.nullAsOptional ?? false,
|
|
1382
|
-
nullAsUndefined: connection.nullAsUndefined ?? false,
|
|
1383
|
-
transform: target.transform,
|
|
1384
|
-
inferLiterals: connection.inferLiterals ?? defaultInferLiteralOptions
|
|
1385
|
-
})
|
|
1386
|
-
)
|
|
1387
|
-
});
|
|
1388
|
-
}
|
|
1094
|
+
() => {
|
|
1389
1095
|
}
|
|
1390
1096
|
)
|
|
1391
1097
|
);
|
|
@@ -1439,98 +1145,13 @@ function checkConnectionByWrapperExpression(params) {
|
|
|
1439
1145
|
});
|
|
1440
1146
|
}
|
|
1441
1147
|
}
|
|
1442
|
-
function getTypeAnnotationState({
|
|
1443
|
-
generated,
|
|
1444
|
-
typeParameter,
|
|
1445
|
-
transform,
|
|
1446
|
-
parser,
|
|
1447
|
-
checker,
|
|
1448
|
-
reservedTypes,
|
|
1449
|
-
nullAsOptional,
|
|
1450
|
-
nullAsUndefined,
|
|
1451
|
-
inferLiterals
|
|
1452
|
-
}) {
|
|
1453
|
-
if (typeParameter.params.length !== 1) {
|
|
1454
|
-
return "INVALID";
|
|
1455
|
-
}
|
|
1456
|
-
const typeNode = typeParameter.params[0];
|
|
1457
|
-
let expected;
|
|
1458
|
-
try {
|
|
1459
|
-
expected = getResolvedTargetByTypeNode({
|
|
1460
|
-
checker,
|
|
1461
|
-
parser,
|
|
1462
|
-
typeNode,
|
|
1463
|
-
reservedTypes
|
|
1464
|
-
});
|
|
1465
|
-
} catch (error) {
|
|
1466
|
-
console.error("[slonik/check-sql] DEBUG: Error in getResolvedTargetByTypeNode:", error);
|
|
1467
|
-
console.error("[slonik/check-sql] DEBUG: typeNode:", typeNode);
|
|
1468
|
-
console.error("[slonik/check-sql] DEBUG: typeNode.type:", typeNode?.type);
|
|
1469
|
-
throw error;
|
|
1470
|
-
}
|
|
1471
|
-
return getResolvedTargetsEquality({
|
|
1472
|
-
expected,
|
|
1473
|
-
generated,
|
|
1474
|
-
nullAsOptional,
|
|
1475
|
-
nullAsUndefined,
|
|
1476
|
-
inferLiterals,
|
|
1477
|
-
transform
|
|
1478
|
-
});
|
|
1479
|
-
}
|
|
1480
|
-
function getResolvedTargetsEquality(params) {
|
|
1481
|
-
if (params.expected === null && params.generated === null) {
|
|
1482
|
-
return {
|
|
1483
|
-
isEqual: true,
|
|
1484
|
-
expected: params.expected,
|
|
1485
|
-
generated: params.generated
|
|
1486
|
-
};
|
|
1487
|
-
}
|
|
1488
|
-
if (params.expected === null || params.generated === null) {
|
|
1489
|
-
return {
|
|
1490
|
-
isEqual: false,
|
|
1491
|
-
expected: params.expected,
|
|
1492
|
-
generated: params.generated
|
|
1493
|
-
};
|
|
1494
|
-
}
|
|
1495
|
-
let expectedString = checkSql_utils.getResolvedTargetComparableString({
|
|
1496
|
-
target: params.expected,
|
|
1497
|
-
nullAsOptional: false,
|
|
1498
|
-
nullAsUndefined: false,
|
|
1499
|
-
inferLiterals: params.inferLiterals
|
|
1500
|
-
});
|
|
1501
|
-
let generatedString = checkSql_utils.getResolvedTargetComparableString({
|
|
1502
|
-
target: params.generated,
|
|
1503
|
-
nullAsOptional: params.nullAsOptional,
|
|
1504
|
-
nullAsUndefined: params.nullAsUndefined,
|
|
1505
|
-
inferLiterals: params.inferLiterals
|
|
1506
|
-
});
|
|
1507
|
-
if (expectedString === null || generatedString === null) {
|
|
1508
|
-
return {
|
|
1509
|
-
isEqual: false,
|
|
1510
|
-
expected: params.expected,
|
|
1511
|
-
generated: params.generated
|
|
1512
|
-
};
|
|
1513
|
-
}
|
|
1514
|
-
expectedString = expectedString.replace(/'/g, '"');
|
|
1515
|
-
generatedString = generatedString.replace(/'/g, '"');
|
|
1516
|
-
expectedString = expectedString.split(", ").sort().join(", ");
|
|
1517
|
-
generatedString = generatedString.split(", ").sort().join(", ");
|
|
1518
|
-
if (params.transform !== void 0) {
|
|
1519
|
-
generatedString = checkSql_utils.transformTypes(generatedString, params.transform);
|
|
1520
|
-
}
|
|
1521
|
-
return {
|
|
1522
|
-
isEqual: expectedString === generatedString,
|
|
1523
|
-
expected: params.expected,
|
|
1524
|
-
generated: params.generated
|
|
1525
|
-
};
|
|
1526
|
-
}
|
|
1527
1148
|
const createRule = utils.ESLintUtils.RuleCreator(() => `https://github.com/gajus/eslint-plugin-slonik`);
|
|
1528
1149
|
const checkSql = createRule({
|
|
1529
1150
|
name: "check-sql",
|
|
1530
1151
|
meta: {
|
|
1531
1152
|
fixable: "code",
|
|
1532
1153
|
docs: {
|
|
1533
|
-
description: "
|
|
1154
|
+
description: "Validate SQL queries against the database schema"
|
|
1534
1155
|
},
|
|
1535
1156
|
messages,
|
|
1536
1157
|
type: "problem",
|