pasika 0.10.44 → 0.10.46
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/eslint/pasika/index.js +72 -1
- package/package.json +1 -1
|
@@ -5184,19 +5184,82 @@ function isEnumLiteralType(node) {
|
|
|
5184
5184
|
function isEnumLiteralUnion(node) {
|
|
5185
5185
|
return node?.type === "TSUnionType" && (node.types?.length ?? 0) >= 2 && (node.types ?? []).every(isEnumLiteralType);
|
|
5186
5186
|
}
|
|
5187
|
+
function isZodCall(node, method) {
|
|
5188
|
+
const { callee } = node;
|
|
5189
|
+
return callee?.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "z" && callee.property.type === "Identifier" && callee.property.name === method;
|
|
5190
|
+
}
|
|
5191
|
+
function propertyName2(property) {
|
|
5192
|
+
if (property.computed) return void 0;
|
|
5193
|
+
if (property.key.type === "Identifier") return property.key.name;
|
|
5194
|
+
if (property.key.type === "Literal" && typeof property.key.value === "string") return property.key.value;
|
|
5195
|
+
return void 0;
|
|
5196
|
+
}
|
|
5197
|
+
function rawZodDiscriminantLiteral(schemaCall, discriminator) {
|
|
5198
|
+
if (!isZodCall(schemaCall, "object")) return void 0;
|
|
5199
|
+
const shape = schemaCall.arguments[0];
|
|
5200
|
+
if (shape?.type !== "ObjectExpression") return void 0;
|
|
5201
|
+
for (const property of shape.properties) {
|
|
5202
|
+
if (property.type !== "Property" || propertyName2(property) !== discriminator) continue;
|
|
5203
|
+
if (property.value.type !== "CallExpression" || !isZodCall(property.value, "literal")) return void 0;
|
|
5204
|
+
const literal = property.value.arguments[0];
|
|
5205
|
+
if (literal?.type === "Literal" && (typeof literal.value === "string" || typeof literal.value === "number")) {
|
|
5206
|
+
return literal;
|
|
5207
|
+
}
|
|
5208
|
+
return void 0;
|
|
5209
|
+
}
|
|
5210
|
+
return void 0;
|
|
5211
|
+
}
|
|
5187
5212
|
var preferEnumRule = {
|
|
5188
5213
|
meta: {
|
|
5189
5214
|
schema: [],
|
|
5190
5215
|
type: "problem",
|
|
5191
5216
|
docs: {
|
|
5192
|
-
description: "Require fixed sets of named string/number values to be TypeScript enums
|
|
5217
|
+
description: "Require fixed sets of named string/number values to be TypeScript enums, including Zod discriminated-union discriminator values."
|
|
5193
5218
|
}
|
|
5194
5219
|
},
|
|
5195
5220
|
create(context) {
|
|
5196
5221
|
const filename = path40.resolve(context.filename);
|
|
5197
5222
|
const sourceRoot = sourceRootOf(context);
|
|
5198
5223
|
if (!filename.startsWith(sourceRoot + path40.sep)) return {};
|
|
5224
|
+
const objectSchemas = /* @__PURE__ */ new Map();
|
|
5225
|
+
const discriminatedUnions = [];
|
|
5226
|
+
const reportedDiscriminants = /* @__PURE__ */ new Set();
|
|
5199
5227
|
return {
|
|
5228
|
+
VariableDeclarator(node) {
|
|
5229
|
+
const { id, init } = node;
|
|
5230
|
+
if (id?.type !== "Identifier" || init?.type !== "CallExpression" || !isZodCall(init, "object")) return;
|
|
5231
|
+
objectSchemas.set(id.name, init);
|
|
5232
|
+
},
|
|
5233
|
+
CallExpression(node) {
|
|
5234
|
+
if (isZodCall(node, "discriminatedUnion")) {
|
|
5235
|
+
discriminatedUnions.push(node);
|
|
5236
|
+
}
|
|
5237
|
+
},
|
|
5238
|
+
"Program:exit"() {
|
|
5239
|
+
for (const unionCall of discriminatedUnions) {
|
|
5240
|
+
const [discriminatorArg, optionsArg] = unionCall.arguments ?? [];
|
|
5241
|
+
if (discriminatorArg?.type !== "Literal" || typeof discriminatorArg.value !== "string" || optionsArg?.type !== "ArrayExpression") {
|
|
5242
|
+
continue;
|
|
5243
|
+
}
|
|
5244
|
+
for (const option of optionsArg.elements) {
|
|
5245
|
+
if (!option || option.type === "SpreadElement") continue;
|
|
5246
|
+
let schemaCall;
|
|
5247
|
+
if (option.type === "Identifier") {
|
|
5248
|
+
schemaCall = objectSchemas.get(option.name);
|
|
5249
|
+
} else if (option.type === "CallExpression" && isZodCall(option, "object")) {
|
|
5250
|
+
schemaCall = option;
|
|
5251
|
+
}
|
|
5252
|
+
if (!schemaCall) continue;
|
|
5253
|
+
const literal = rawZodDiscriminantLiteral(schemaCall, discriminatorArg.value);
|
|
5254
|
+
if (!literal || reportedDiscriminants.has(literal)) continue;
|
|
5255
|
+
reportedDiscriminants.add(literal);
|
|
5256
|
+
context.report({
|
|
5257
|
+
node: literal,
|
|
5258
|
+
message: "A Zod discriminated-union discriminator literal must use a TypeScript enum member. See docs/next-codebase-guide/rules/constants-rule.md"
|
|
5259
|
+
});
|
|
5260
|
+
}
|
|
5261
|
+
}
|
|
5262
|
+
},
|
|
5200
5263
|
TSAsExpression(node) {
|
|
5201
5264
|
if (!isConstAssertion(node)) return;
|
|
5202
5265
|
const expression = node.expression;
|
|
@@ -5214,6 +5277,14 @@ var preferEnumRule = {
|
|
|
5214
5277
|
node,
|
|
5215
5278
|
message: "A named union made only of string or number literals must be a TypeScript enum. See docs/next-codebase-guide/rules/constants-rule.md"
|
|
5216
5279
|
});
|
|
5280
|
+
},
|
|
5281
|
+
TSPropertySignature(node) {
|
|
5282
|
+
const typeAnnotation = node.typeAnnotation?.typeAnnotation;
|
|
5283
|
+
if (!isEnumLiteralUnion(typeAnnotation)) return;
|
|
5284
|
+
context.report({
|
|
5285
|
+
node,
|
|
5286
|
+
message: "A property whose type is a union made only of string or number literals must use a TypeScript enum. See docs/next-codebase-guide/rules/constants-rule.md"
|
|
5287
|
+
});
|
|
5217
5288
|
}
|
|
5218
5289
|
};
|
|
5219
5290
|
}
|