pasika 0.10.95 → 0.10.97
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.d.ts +3 -2
- package/dist/eslint/pasika/index.js +636 -149
- package/package.json +1 -1
|
@@ -444,8 +444,8 @@ function parseModule(file) {
|
|
|
444
444
|
}
|
|
445
445
|
continue;
|
|
446
446
|
}
|
|
447
|
-
const
|
|
448
|
-
if (!
|
|
447
|
+
const isExported3 = ts.canHaveModifiers(statement) ? (ts.getModifiers(statement) ?? []).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) : false;
|
|
448
|
+
if (!isExported3) continue;
|
|
449
449
|
if (ts.isFunctionDeclaration(statement) && statement.name) {
|
|
450
450
|
const name = statement.name.text;
|
|
451
451
|
exports.push({
|
|
@@ -3261,19 +3261,34 @@ var enumPlacementRule = {
|
|
|
3261
3261
|
schema: [],
|
|
3262
3262
|
type: "problem",
|
|
3263
3263
|
docs: {
|
|
3264
|
-
description: "
|
|
3264
|
+
description: "Keep file-local enums local, place shared enums in constants/, and avoid one-member enums."
|
|
3265
3265
|
}
|
|
3266
3266
|
},
|
|
3267
3267
|
create(context) {
|
|
3268
3268
|
const filename = path25.resolve(context.filename);
|
|
3269
3269
|
const sourceRoot = sourceRootOf(context);
|
|
3270
3270
|
if (!filename.startsWith(sourceRoot + path25.sep)) return {};
|
|
3271
|
-
|
|
3271
|
+
const inConstantsFolder = path25.basename(path25.dirname(filename)) === "constants";
|
|
3272
|
+
const index = getProjectIndex(sourceRoot);
|
|
3272
3273
|
return {
|
|
3273
3274
|
TSEnumDeclaration(node) {
|
|
3275
|
+
const enumBody = "body" in node ? node.body : void 0;
|
|
3276
|
+
const members = enumBody && typeof enumBody === "object" && "members" in enumBody ? enumBody.members : void 0;
|
|
3277
|
+
const enumId = "id" in node ? node.id : void 0;
|
|
3278
|
+
const enumName = enumId && typeof enumId === "object" && "name" in enumId ? enumId.name : void 0;
|
|
3279
|
+
if (!Array.isArray(members) || typeof enumName !== "string") return;
|
|
3280
|
+
if (members.length === 1) {
|
|
3281
|
+
context.report({
|
|
3282
|
+
node,
|
|
3283
|
+
message: "A single named string or number value must be a const, not a one-member enum. See docs/next-codebase-guide/rules/constants-rule.md"
|
|
3284
|
+
});
|
|
3285
|
+
return;
|
|
3286
|
+
}
|
|
3287
|
+
const shared = (index?.symbolConsumers.get(symbolKey(filename, enumName))?.size ?? 0) > 0;
|
|
3288
|
+
if (inConstantsFolder || !shared) return;
|
|
3274
3289
|
context.report({
|
|
3275
3290
|
node,
|
|
3276
|
-
message: "
|
|
3291
|
+
message: "An enum imported by another file must live in a constants/ folder at its CCF; keep file-local enums beside their consumers. See docs/next-codebase-guide/rules/constants-rule.md"
|
|
3277
3292
|
});
|
|
3278
3293
|
}
|
|
3279
3294
|
};
|
|
@@ -3287,7 +3302,7 @@ var fileLengthRule = {
|
|
|
3287
3302
|
schema: [],
|
|
3288
3303
|
type: "problem",
|
|
3289
3304
|
docs: {
|
|
3290
|
-
description: "Require application
|
|
3305
|
+
description: "Require TypeScript files and application JavaScript files to stay at or below 300 lines."
|
|
3291
3306
|
}
|
|
3292
3307
|
},
|
|
3293
3308
|
create(context) {
|
|
@@ -4614,10 +4629,10 @@ function localePlacement(text) {
|
|
|
4614
4629
|
const sourceFile = ts6.createSourceFile("locales.ts", text, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
|
|
4615
4630
|
for (const statement of sourceFile.statements) {
|
|
4616
4631
|
if (!ts6.isVariableStatement(statement)) continue;
|
|
4617
|
-
const
|
|
4632
|
+
const isExported3 = (ts6.getModifiers(statement) ?? []).some(
|
|
4618
4633
|
(modifier) => modifier.kind === ts6.SyntaxKind.ExportKeyword
|
|
4619
4634
|
);
|
|
4620
|
-
if (!
|
|
4635
|
+
if (!isExported3) continue;
|
|
4621
4636
|
for (const declaration of statement.declarationList.declarations) {
|
|
4622
4637
|
if (!ts6.isIdentifier(declaration.name) || declaration.name.text !== "locales") continue;
|
|
4623
4638
|
if (!declaration.initializer || !ts6.isObjectLiteralExpression(declaration.initializer)) continue;
|
|
@@ -6361,7 +6376,7 @@ var preferEnumRule = {
|
|
|
6361
6376
|
}
|
|
6362
6377
|
for (const unionCall of discriminatedUnions) {
|
|
6363
6378
|
const [discriminatorArg, optionsArg] = unionCall.arguments ?? [];
|
|
6364
|
-
if (discriminatorArg?.type !== "Literal" || typeof discriminatorArg.value !== "string" || optionsArg?.type !== "ArrayExpression") {
|
|
6379
|
+
if (discriminatorArg?.type !== "Literal" || typeof discriminatorArg.value !== "string" || optionsArg?.type !== "ArrayExpression" || optionsArg.elements.length < 2) {
|
|
6365
6380
|
continue;
|
|
6366
6381
|
}
|
|
6367
6382
|
for (const option of optionsArg.elements) {
|
|
@@ -6391,7 +6406,7 @@ var preferEnumRule = {
|
|
|
6391
6406
|
}
|
|
6392
6407
|
const expression = node.expression;
|
|
6393
6408
|
if (!expression || expression.type !== "ObjectExpression") return;
|
|
6394
|
-
if (expression.properties.length
|
|
6409
|
+
if (expression.properties.length < 2) return;
|
|
6395
6410
|
if (!expression.properties.every(isEnumConvertibleProperty)) return;
|
|
6396
6411
|
context.report({
|
|
6397
6412
|
node,
|
|
@@ -7109,7 +7124,7 @@ var repeatedNumericValueRule = {
|
|
|
7109
7124
|
schema: [],
|
|
7110
7125
|
type: "problem",
|
|
7111
7126
|
docs: {
|
|
7112
|
-
description: "Require repeated named numeric values across production files to use one
|
|
7127
|
+
description: "Require repeated named numeric values across production files to use one shared constant."
|
|
7113
7128
|
}
|
|
7114
7129
|
},
|
|
7115
7130
|
create(context) {
|
|
@@ -7144,7 +7159,467 @@ var repeatedNumericValueRule = {
|
|
|
7144
7159
|
context.report({
|
|
7145
7160
|
node,
|
|
7146
7161
|
loc: { line: literal.line, column: 0 },
|
|
7147
|
-
message: `The numeric value ${String(literal.value)} is repeated for the "${literal.semanticName}" semantic slot in ${String(files.size)} production files. Extract one constant
|
|
7162
|
+
message: `The numeric value ${String(literal.value)} is repeated for the "${literal.semanticName}" semantic slot in ${String(files.size)} production files. Extract one constant at their CCF and import it instead. See docs/next-codebase-guide/rules/constants-rule.md`
|
|
7163
|
+
});
|
|
7164
|
+
}
|
|
7165
|
+
}
|
|
7166
|
+
};
|
|
7167
|
+
}
|
|
7168
|
+
};
|
|
7169
|
+
|
|
7170
|
+
// eslint/rules/repeated-semantic-literal.ts
|
|
7171
|
+
import path49 from "path";
|
|
7172
|
+
|
|
7173
|
+
// eslint/project/semantic-literals.ts
|
|
7174
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
7175
|
+
import path47 from "path";
|
|
7176
|
+
import ts10 from "typescript";
|
|
7177
|
+
var excludedProperties = /* @__PURE__ */ new Set([
|
|
7178
|
+
"label",
|
|
7179
|
+
"title",
|
|
7180
|
+
"description",
|
|
7181
|
+
"message",
|
|
7182
|
+
"text",
|
|
7183
|
+
"placeholder",
|
|
7184
|
+
"className",
|
|
7185
|
+
"content",
|
|
7186
|
+
"alt",
|
|
7187
|
+
"src",
|
|
7188
|
+
"href",
|
|
7189
|
+
"url",
|
|
7190
|
+
"html",
|
|
7191
|
+
"ariaLabel",
|
|
7192
|
+
"testId"
|
|
7193
|
+
]);
|
|
7194
|
+
var semanticProperties = /* @__PURE__ */ new Set(["status", "phase", "event", "eventName", "action", "storageKey", "endpoint"]);
|
|
7195
|
+
var semanticVariableName = /route|path|key|status|event|timeout|delay|token|column|endpoint|limit|duration/i;
|
|
7196
|
+
var columnMethods = /* @__PURE__ */ new Set([
|
|
7197
|
+
"eq",
|
|
7198
|
+
"neq",
|
|
7199
|
+
"gt",
|
|
7200
|
+
"gte",
|
|
7201
|
+
"lt",
|
|
7202
|
+
"lte",
|
|
7203
|
+
"like",
|
|
7204
|
+
"ilike",
|
|
7205
|
+
"is",
|
|
7206
|
+
"in",
|
|
7207
|
+
"order",
|
|
7208
|
+
"filter",
|
|
7209
|
+
"not"
|
|
7210
|
+
]);
|
|
7211
|
+
var eventMethods = /* @__PURE__ */ new Set(["emit", "on", "off", "once", "addListener", "removeListener"]);
|
|
7212
|
+
var ignoredNumbers = /* @__PURE__ */ new Set([-1, 0, 1]);
|
|
7213
|
+
function isProductionSource(file, root) {
|
|
7214
|
+
const parts = path47.relative(root, file).split(path47.sep);
|
|
7215
|
+
return !(/\.(?:test|spec|mock)\.[^.]+$/.test(path47.basename(file)) || parts.some((part) => part === "__tests__" || part === "__mocks__" || part === "mocks"));
|
|
7216
|
+
}
|
|
7217
|
+
function featureOf(file, root) {
|
|
7218
|
+
const parts = path47.relative(root, file).split(path47.sep);
|
|
7219
|
+
if (parts[0] === "features" && parts[1]) return `feature:${parts[1]}`;
|
|
7220
|
+
return `layer:${parts[0] ?? "src"}`;
|
|
7221
|
+
}
|
|
7222
|
+
function nameOf(property) {
|
|
7223
|
+
if (ts10.isIdentifier(property) || ts10.isStringLiteral(property)) return property.text;
|
|
7224
|
+
return void 0;
|
|
7225
|
+
}
|
|
7226
|
+
function literalOf(node) {
|
|
7227
|
+
if (ts10.isStringLiteral(node)) return node.text;
|
|
7228
|
+
if (ts10.isNumericLiteral(node)) return Number(node.text.replaceAll("_", ""));
|
|
7229
|
+
if (ts10.isPrefixUnaryExpression(node) && node.operator === ts10.SyntaxKind.MinusToken && ts10.isNumericLiteral(node.operand)) {
|
|
7230
|
+
return -Number(node.operand.text.replaceAll("_", ""));
|
|
7231
|
+
}
|
|
7232
|
+
return void 0;
|
|
7233
|
+
}
|
|
7234
|
+
function isLiteralRoot(node) {
|
|
7235
|
+
if (ts10.isPrefixUnaryExpression(node)) return literalOf(node) !== void 0;
|
|
7236
|
+
return (ts10.isStringLiteral(node) || ts10.isNumericLiteral(node)) && !(ts10.isPrefixUnaryExpression(node.parent) && node.parent.operand === node);
|
|
7237
|
+
}
|
|
7238
|
+
function invocation(node) {
|
|
7239
|
+
if (ts10.isIdentifier(node.expression)) return { method: node.expression.text };
|
|
7240
|
+
if (ts10.isPropertyAccessExpression(node.expression)) {
|
|
7241
|
+
const receiver = node.expression.expression.getText();
|
|
7242
|
+
if (!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)?$/.test(receiver)) return void 0;
|
|
7243
|
+
return { method: node.expression.name.text, receiver };
|
|
7244
|
+
}
|
|
7245
|
+
return void 0;
|
|
7246
|
+
}
|
|
7247
|
+
function isPathname(node) {
|
|
7248
|
+
return ts10.isPropertyAccessExpression(node) && node.name.text === "pathname";
|
|
7249
|
+
}
|
|
7250
|
+
function contextFor(node, value, file, root) {
|
|
7251
|
+
if (typeof value === "number" && ignoredNumbers.has(value)) return void 0;
|
|
7252
|
+
if (typeof value === "string" && (value.length < 3 || /\s/.test(value))) return void 0;
|
|
7253
|
+
const parent = node.parent;
|
|
7254
|
+
const scope = featureOf(file, root);
|
|
7255
|
+
const isApiRoute = typeof value === "string" && value.startsWith("/api/") && !/[?&#\s]/.test(value);
|
|
7256
|
+
const route = () => ({ role: "api-route", family: "api-route" });
|
|
7257
|
+
if (ts10.isPropertyAssignment(parent) && parent.initializer === node) {
|
|
7258
|
+
const name = nameOf(parent.name);
|
|
7259
|
+
if (!name) return void 0;
|
|
7260
|
+
if (name === "path" && isApiRoute) return route();
|
|
7261
|
+
if (!semanticProperties.has(name)) return void 0;
|
|
7262
|
+
if (typeof value === "number") return void 0;
|
|
7263
|
+
if (isApiRoute && /route|path|endpoint/i.test(name)) return route();
|
|
7264
|
+
return { role: `property:${name}:${scope}`, family: `property:${name}` };
|
|
7265
|
+
}
|
|
7266
|
+
if (ts10.isVariableDeclaration(parent) && parent.initializer === node && ts10.isIdentifier(parent.name)) {
|
|
7267
|
+
if (typeof value === "number") return void 0;
|
|
7268
|
+
const name = parent.name.text;
|
|
7269
|
+
if (excludedProperties.has(name) || !semanticVariableName.test(name)) return void 0;
|
|
7270
|
+
if (isApiRoute && /route|path|endpoint/i.test(name)) return route();
|
|
7271
|
+
return { role: `variable:${name}:${scope}`, family: `variable:${name}` };
|
|
7272
|
+
}
|
|
7273
|
+
if (ts10.isCallExpression(parent)) {
|
|
7274
|
+
const position = parent.arguments.findIndex((argument) => argument === node);
|
|
7275
|
+
if (position < 0) return void 0;
|
|
7276
|
+
const call = invocation(parent);
|
|
7277
|
+
if (!call) return void 0;
|
|
7278
|
+
if (isApiRoute && position === 0 && (call.method === "fetch" || call.method === "zodFetch")) return route();
|
|
7279
|
+
if (typeof value === "number" && position === 1 && (call.method === "setTimeout" || call.method === "setInterval")) {
|
|
7280
|
+
return { role: `timer:${call.method}:${scope}`, family: "timer" };
|
|
7281
|
+
}
|
|
7282
|
+
if (typeof value === "string" && position === 0 && call.receiver && (call.receiver === "localStorage" || call.receiver === "sessionStorage") && ["getItem", "setItem", "removeItem"].includes(call.method)) {
|
|
7283
|
+
return { role: `storage:${call.receiver}`, family: "storage" };
|
|
7284
|
+
}
|
|
7285
|
+
if (typeof value === "string" && position === 0 && call.receiver && eventMethods.has(call.method) && /(?:event|bus|socket|emitter)/i.test(call.receiver)) {
|
|
7286
|
+
return { role: `event:${call.receiver}`, family: "event" };
|
|
7287
|
+
}
|
|
7288
|
+
if (typeof value === "string" && position === 0 && call.receiver && columnMethods.has(call.method) && value.length > 3 && /^[a-z][a-z0-9_]*$/.test(value)) {
|
|
7289
|
+
return { role: `column:${scope}`, family: "column" };
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
if (isApiRoute && ts10.isBinaryExpression(parent) && (parent.operatorToken.kind === ts10.SyntaxKind.EqualsEqualsEqualsToken || parent.operatorToken.kind === ts10.SyntaxKind.ExclamationEqualsEqualsToken) && (parent.left === node && isPathname(parent.right) || parent.right === node && isPathname(parent.left))) {
|
|
7293
|
+
return route();
|
|
7294
|
+
}
|
|
7295
|
+
if (isApiRoute && ts10.isCallExpression(parent) && parent.arguments[0] === node && ts10.isPropertyAccessExpression(parent.expression) && parent.expression.name.text === "startsWith" && isPathname(parent.expression.expression)) {
|
|
7296
|
+
return route();
|
|
7297
|
+
}
|
|
7298
|
+
return void 0;
|
|
7299
|
+
}
|
|
7300
|
+
function isExported2(node) {
|
|
7301
|
+
return ts10.canHaveModifiers(node) && (ts10.getModifiers(node) ?? []).some((modifier) => modifier.kind === ts10.SyntaxKind.ExportKeyword);
|
|
7302
|
+
}
|
|
7303
|
+
function parse(file, root, output) {
|
|
7304
|
+
if (!isProductionSource(file, root)) return;
|
|
7305
|
+
const source = ts10.createSourceFile(
|
|
7306
|
+
file,
|
|
7307
|
+
readFileSync10(file, "utf8"),
|
|
7308
|
+
ts10.ScriptTarget.Latest,
|
|
7309
|
+
true,
|
|
7310
|
+
file.endsWith(".tsx") || file.endsWith(".jsx") ? ts10.ScriptKind.TSX : ts10.ScriptKind.TS
|
|
7311
|
+
);
|
|
7312
|
+
const inConstants = path47.relative(root, file).split(path47.sep).includes("constants");
|
|
7313
|
+
for (const statement of source.statements) {
|
|
7314
|
+
if (inConstants && ts10.isEnumDeclaration(statement) && isExported2(statement)) {
|
|
7315
|
+
for (const member of statement.members) {
|
|
7316
|
+
const value = member.initializer && literalOf(member.initializer);
|
|
7317
|
+
const memberName9 = nameOf(member.name);
|
|
7318
|
+
if (value === void 0 || !memberName9) continue;
|
|
7319
|
+
output.canonicals.push({
|
|
7320
|
+
file,
|
|
7321
|
+
name: memberName9,
|
|
7322
|
+
owner: statement.name.text,
|
|
7323
|
+
kind: typeof value === "string" ? "string" : "number",
|
|
7324
|
+
value
|
|
7325
|
+
});
|
|
7326
|
+
}
|
|
7327
|
+
}
|
|
7328
|
+
if (inConstants && ts10.isVariableStatement(statement) && isExported2(statement)) {
|
|
7329
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
7330
|
+
if (!ts10.isIdentifier(declaration.name) || !declaration.initializer) continue;
|
|
7331
|
+
const value = literalOf(declaration.initializer);
|
|
7332
|
+
if (value === void 0) continue;
|
|
7333
|
+
output.canonicals.push({
|
|
7334
|
+
file,
|
|
7335
|
+
name: declaration.name.text,
|
|
7336
|
+
kind: typeof value === "string" ? "string" : "number",
|
|
7337
|
+
value
|
|
7338
|
+
});
|
|
7339
|
+
}
|
|
7340
|
+
}
|
|
7341
|
+
}
|
|
7342
|
+
const visit = (node) => {
|
|
7343
|
+
if (isLiteralRoot(node)) {
|
|
7344
|
+
const value = literalOf(node);
|
|
7345
|
+
if (value !== void 0) {
|
|
7346
|
+
const semantic = contextFor(node, value, file, root);
|
|
7347
|
+
if (semantic) {
|
|
7348
|
+
const declaration = node.parent;
|
|
7349
|
+
const isCanonicalDefinition = inConstants && (ts10.isVariableDeclaration(declaration) && ts10.isVariableStatement(declaration.parent.parent) && isExported2(declaration.parent.parent) || ts10.isEnumMember(declaration));
|
|
7350
|
+
if ((!inConstants || semantic.family === "api-route") && !isCanonicalDefinition) {
|
|
7351
|
+
const position = source.getLineAndCharacterOfPosition(node.getStart(source));
|
|
7352
|
+
output.uses.push({
|
|
7353
|
+
file,
|
|
7354
|
+
kind: typeof value === "string" ? "string" : "number",
|
|
7355
|
+
value,
|
|
7356
|
+
line: position.line + 1,
|
|
7357
|
+
column: position.character,
|
|
7358
|
+
...semantic
|
|
7359
|
+
});
|
|
7360
|
+
}
|
|
7361
|
+
}
|
|
7362
|
+
}
|
|
7363
|
+
}
|
|
7364
|
+
ts10.forEachChild(node, visit);
|
|
7365
|
+
};
|
|
7366
|
+
visit(source);
|
|
7367
|
+
}
|
|
7368
|
+
var cache3 = /* @__PURE__ */ new WeakMap();
|
|
7369
|
+
function getSemanticLiteralIndex(index) {
|
|
7370
|
+
const previous = cache3.get(index);
|
|
7371
|
+
if (previous) return previous;
|
|
7372
|
+
const result = { uses: [], canonicals: [] };
|
|
7373
|
+
for (const file of index.modules.keys()) {
|
|
7374
|
+
try {
|
|
7375
|
+
parse(file, index.sourceRoot, result);
|
|
7376
|
+
} catch {
|
|
7377
|
+
}
|
|
7378
|
+
}
|
|
7379
|
+
cache3.set(index, result);
|
|
7380
|
+
return result;
|
|
7381
|
+
}
|
|
7382
|
+
|
|
7383
|
+
// eslint/rules/imported-enum-literals.ts
|
|
7384
|
+
import path48 from "path";
|
|
7385
|
+
import ts11 from "typescript";
|
|
7386
|
+
var columnMethods2 = /* @__PURE__ */ new Set([
|
|
7387
|
+
"eq",
|
|
7388
|
+
"neq",
|
|
7389
|
+
"gt",
|
|
7390
|
+
"gte",
|
|
7391
|
+
"lt",
|
|
7392
|
+
"lte",
|
|
7393
|
+
"like",
|
|
7394
|
+
"ilike",
|
|
7395
|
+
"is",
|
|
7396
|
+
"in",
|
|
7397
|
+
"order",
|
|
7398
|
+
"filter",
|
|
7399
|
+
"not"
|
|
7400
|
+
]);
|
|
7401
|
+
function memberName6(name) {
|
|
7402
|
+
if (ts11.isIdentifier(name) || ts11.isStringLiteral(name)) return name.text;
|
|
7403
|
+
return void 0;
|
|
7404
|
+
}
|
|
7405
|
+
function isWithin3(root, file) {
|
|
7406
|
+
const relative = path48.relative(root, file);
|
|
7407
|
+
return relative === "" || !relative.startsWith("..") && !path48.isAbsolute(relative);
|
|
7408
|
+
}
|
|
7409
|
+
function domainOf(name) {
|
|
7410
|
+
if (name.endsWith("ColumnEnum")) return "column";
|
|
7411
|
+
if (name.endsWith("Route") || name.endsWith("RouteEnum")) return "route";
|
|
7412
|
+
return void 0;
|
|
7413
|
+
}
|
|
7414
|
+
function importedEnums(file, checker, sourceRoot, importedNames) {
|
|
7415
|
+
const matches = /* @__PURE__ */ new Map();
|
|
7416
|
+
for (const statement of file.statements) {
|
|
7417
|
+
if (!ts11.isImportDeclaration(statement) || !statement.importClause?.namedBindings || !ts11.isNamedImports(statement.importClause.namedBindings)) {
|
|
7418
|
+
continue;
|
|
7419
|
+
}
|
|
7420
|
+
for (const specifier of statement.importClause.namedBindings.elements) {
|
|
7421
|
+
if (!importedNames.has(specifier.name.text)) continue;
|
|
7422
|
+
const symbol = checker.getSymbolAtLocation(specifier.name);
|
|
7423
|
+
if (!symbol) continue;
|
|
7424
|
+
const resolved = symbol.flags === ts11.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
|
|
7425
|
+
for (const declaration of resolved.declarations ?? []) {
|
|
7426
|
+
if (!ts11.isEnumDeclaration(declaration)) continue;
|
|
7427
|
+
const declarationFile = path48.resolve(declaration.getSourceFile().fileName);
|
|
7428
|
+
if (!isWithin3(sourceRoot, declarationFile)) continue;
|
|
7429
|
+
const domain = domainOf(declaration.name.text);
|
|
7430
|
+
if (!domain) continue;
|
|
7431
|
+
for (const member of declaration.members) {
|
|
7432
|
+
if (!member.initializer || !ts11.isStringLiteral(member.initializer)) continue;
|
|
7433
|
+
const name = memberName6(member.name);
|
|
7434
|
+
if (!name) continue;
|
|
7435
|
+
const entries = matches.get(member.initializer.text) ?? [];
|
|
7436
|
+
entries.push({
|
|
7437
|
+
reference: `${specifier.name.text}.${name}`,
|
|
7438
|
+
domain,
|
|
7439
|
+
sourceFile: declarationFile
|
|
7440
|
+
});
|
|
7441
|
+
matches.set(member.initializer.text, entries);
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7444
|
+
}
|
|
7445
|
+
}
|
|
7446
|
+
return matches;
|
|
7447
|
+
}
|
|
7448
|
+
function isPathname2(node) {
|
|
7449
|
+
return ts11.isPropertyAccessExpression(node) && node.name.text === "pathname";
|
|
7450
|
+
}
|
|
7451
|
+
function domainForUse(node) {
|
|
7452
|
+
const parent = node.parent;
|
|
7453
|
+
if (ts11.isPropertyAssignment(parent) && parent.initializer === node && memberName6(parent.name) === "path") {
|
|
7454
|
+
return "route";
|
|
7455
|
+
}
|
|
7456
|
+
if (ts11.isCallExpression(parent) && parent.arguments[0] === node && ts11.isPropertyAccessExpression(parent.expression)) {
|
|
7457
|
+
const { expression, name } = parent.expression;
|
|
7458
|
+
if (columnMethods2.has(name.text)) return "column";
|
|
7459
|
+
if (name.text === "startsWith" && isPathname2(expression)) return "route";
|
|
7460
|
+
}
|
|
7461
|
+
if (ts11.isBinaryExpression(parent) && (parent.operatorToken.kind === ts11.SyntaxKind.EqualsEqualsEqualsToken || parent.operatorToken.kind === ts11.SyntaxKind.ExclamationEqualsEqualsToken) && (parent.left === node && isPathname2(parent.right) || parent.right === node && isPathname2(parent.left))) {
|
|
7462
|
+
return "route";
|
|
7463
|
+
}
|
|
7464
|
+
return void 0;
|
|
7465
|
+
}
|
|
7466
|
+
function importedEnumLiteralUses(context, root) {
|
|
7467
|
+
const filename = path48.resolve(context.filename);
|
|
7468
|
+
if (!isWithin3(root, filename)) return [];
|
|
7469
|
+
const services = typedParserServices(context.sourceCode.parserServices);
|
|
7470
|
+
if (!services) return [];
|
|
7471
|
+
const file = services.program.getSourceFile(filename);
|
|
7472
|
+
if (file?.text !== context.sourceCode.text) return [];
|
|
7473
|
+
const importedNames = /* @__PURE__ */ new Set();
|
|
7474
|
+
for (const statement of context.sourceCode.ast.body) {
|
|
7475
|
+
if (statement.type !== "ImportDeclaration") continue;
|
|
7476
|
+
for (const specifier of statement.specifiers) importedNames.add(specifier.local.name);
|
|
7477
|
+
}
|
|
7478
|
+
if (importedNames.size === 0) return [];
|
|
7479
|
+
const matches = importedEnums(file, services.program.getTypeChecker(), root, importedNames);
|
|
7480
|
+
if (matches.size === 0) return [];
|
|
7481
|
+
const uses = [];
|
|
7482
|
+
const visit = (node) => {
|
|
7483
|
+
if (ts11.isStringLiteral(node)) {
|
|
7484
|
+
const domain = domainForUse(node);
|
|
7485
|
+
const candidates = matches.get(node.text)?.filter((entry) => entry.domain === domain) ?? [];
|
|
7486
|
+
if (candidates.length === 1) {
|
|
7487
|
+
const match = candidates[0];
|
|
7488
|
+
if (match) {
|
|
7489
|
+
const position = file.getLineAndCharacterOfPosition(node.getStart(file));
|
|
7490
|
+
uses.push({
|
|
7491
|
+
reference: match.reference,
|
|
7492
|
+
sourceFile: match.sourceFile,
|
|
7493
|
+
value: node.text,
|
|
7494
|
+
line: position.line + 1,
|
|
7495
|
+
column: position.character
|
|
7496
|
+
});
|
|
7497
|
+
}
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
ts11.forEachChild(node, visit);
|
|
7501
|
+
};
|
|
7502
|
+
visit(file);
|
|
7503
|
+
return uses;
|
|
7504
|
+
}
|
|
7505
|
+
|
|
7506
|
+
// eslint/rules/repeated-semantic-literal.ts
|
|
7507
|
+
var DOC6 = "See docs/next-codebase-guide/rules/constants-rule.md";
|
|
7508
|
+
function canonicalMatches(use, canonical, sourceRoot) {
|
|
7509
|
+
if (use.kind !== canonical.kind || use.value !== canonical.value) return false;
|
|
7510
|
+
const name = canonical.owner ?? canonical.name;
|
|
7511
|
+
if (use.family === "api-route") return /route|path|endpoint/i.test(name);
|
|
7512
|
+
if (use.family === "column") return /column/i.test(name);
|
|
7513
|
+
if (use.family === "timer") return /timeout|delay|interval/i.test(name);
|
|
7514
|
+
if (use.family === "storage") return /key|storage/i.test(name);
|
|
7515
|
+
if (use.family === "event") return /event/i.test(name);
|
|
7516
|
+
if (use.family.startsWith("property:") || use.family.startsWith("variable:")) {
|
|
7517
|
+
const semanticName2 = use.family.split(":")[1];
|
|
7518
|
+
if (!semanticName2 || !name.toLowerCase().includes(semanticName2.toLowerCase())) return false;
|
|
7519
|
+
const location = featureOf(canonical.file, sourceRoot);
|
|
7520
|
+
return location === featureOf(use.file, sourceRoot) || path49.relative(sourceRoot, canonical.file).split(path49.sep)[0] === "constants";
|
|
7521
|
+
}
|
|
7522
|
+
return false;
|
|
7523
|
+
}
|
|
7524
|
+
function formatValue(use) {
|
|
7525
|
+
return typeof use.value === "string" ? JSON.stringify(use.value) : String(use.value);
|
|
7526
|
+
}
|
|
7527
|
+
function canonicalName(canonical) {
|
|
7528
|
+
return canonical.owner ? `${canonical.owner}.${canonical.name}` : canonical.name;
|
|
7529
|
+
}
|
|
7530
|
+
function messageFor(use, matches, duplicateRouteDomains, existingRouteEnum, root) {
|
|
7531
|
+
const count = new Set(matches.map((match) => match.file)).size;
|
|
7532
|
+
const kind = use.kind === "string" ? "string" : "numeric";
|
|
7533
|
+
if (use.family === "api-route" && existingRouteEnum?.owner) {
|
|
7534
|
+
const location = path49.relative(root, existingRouteEnum.file).replaceAll(path49.sep, "/");
|
|
7535
|
+
return `The route ${formatValue(use)} repeats; add a member to existing ${existingRouteEnum.owner} in src/${location} and reuse it. ${DOC6}`;
|
|
7536
|
+
}
|
|
7537
|
+
if (count === 1) {
|
|
7538
|
+
return `The ${kind} literal ${formatValue(use)} repeats in the same semantic role in this file. Extract a file-local const. ${DOC6}`;
|
|
7539
|
+
}
|
|
7540
|
+
const placement = use.family === "api-route" && duplicateRouteDomains.has(use.role) ? "a shared enum for this closed route domain" : "one shared const";
|
|
7541
|
+
return `The ${kind} literal ${formatValue(use)} repeats in ${String(count)} production files for the same semantic role. Extract ${placement} at the consumers' CCF and import it. ${DOC6}`;
|
|
7542
|
+
}
|
|
7543
|
+
var repeatedSemanticLiteralRule = {
|
|
7544
|
+
meta: {
|
|
7545
|
+
schema: [],
|
|
7546
|
+
type: "problem",
|
|
7547
|
+
docs: {
|
|
7548
|
+
description: "Reuse canonical string/number values or extract semantically repeated literals at their CCF."
|
|
7549
|
+
}
|
|
7550
|
+
},
|
|
7551
|
+
create(context) {
|
|
7552
|
+
const root = sourceRootOf(context);
|
|
7553
|
+
const file = path49.resolve(context.filename);
|
|
7554
|
+
if (!isProductionSource(file, root)) return {};
|
|
7555
|
+
const project = getProjectIndex(root);
|
|
7556
|
+
if (!project?.modules.has(file)) return {};
|
|
7557
|
+
const index = getSemanticLiteralIndex(project);
|
|
7558
|
+
const current = index.uses.filter((entry) => entry.file === file);
|
|
7559
|
+
const imported = importedEnumLiteralUses(context, root);
|
|
7560
|
+
if (current.length === 0 && imported.length === 0) return {};
|
|
7561
|
+
const groups = /* @__PURE__ */ new Map();
|
|
7562
|
+
for (const use of index.uses) {
|
|
7563
|
+
const key = `${use.kind}\0${String(use.value)}\0${use.role}`;
|
|
7564
|
+
const group = groups.get(key) ?? [];
|
|
7565
|
+
group.push(use);
|
|
7566
|
+
groups.set(key, group);
|
|
7567
|
+
}
|
|
7568
|
+
const duplicatedApiRoutes = /* @__PURE__ */ new Set();
|
|
7569
|
+
const routeValues = /* @__PURE__ */ new Map();
|
|
7570
|
+
for (const group of groups.values()) {
|
|
7571
|
+
const first = group[0];
|
|
7572
|
+
if (group.length < 2 || first?.family !== "api-route") continue;
|
|
7573
|
+
const values = routeValues.get(first.role) ?? /* @__PURE__ */ new Set();
|
|
7574
|
+
values.add(String(first.value));
|
|
7575
|
+
routeValues.set(first.role, values);
|
|
7576
|
+
}
|
|
7577
|
+
for (const [role, values] of routeValues) {
|
|
7578
|
+
if (values.size >= 2) duplicatedApiRoutes.add(role);
|
|
7579
|
+
}
|
|
7580
|
+
const routeDomains = /* @__PURE__ */ new Map();
|
|
7581
|
+
for (const canonical of index.canonicals) {
|
|
7582
|
+
if (canonical.owner && /^ApiRoute(?:Enum)?$/.test(canonical.owner)) {
|
|
7583
|
+
routeDomains.set(`${canonical.file}:${canonical.owner}`, canonical);
|
|
7584
|
+
}
|
|
7585
|
+
}
|
|
7586
|
+
const existingRouteEnum = routeDomains.size === 1 ? [...routeDomains.values()][0] : void 0;
|
|
7587
|
+
const recognized = new Set(imported.map((use) => `${String(use.line)}:${String(use.column)}`));
|
|
7588
|
+
return {
|
|
7589
|
+
Program(node) {
|
|
7590
|
+
for (const use of imported) {
|
|
7591
|
+
const relative = path49.relative(root, use.sourceFile).replaceAll(path49.sep, "/");
|
|
7592
|
+
context.report({
|
|
7593
|
+
node,
|
|
7594
|
+
loc: { line: use.line, column: use.column },
|
|
7595
|
+
message: `Reuse ${use.reference} from src/${relative} instead of raw ${JSON.stringify(use.value)}. ${DOC6}`
|
|
7596
|
+
});
|
|
7597
|
+
}
|
|
7598
|
+
for (const use of current) {
|
|
7599
|
+
if (recognized.has(`${String(use.line)}:${String(use.column)}`)) continue;
|
|
7600
|
+
const candidates = index.canonicals.filter(
|
|
7601
|
+
(canonical) => canonicalMatches(use, canonical, root) && canonical.file !== file
|
|
7602
|
+
);
|
|
7603
|
+
if (candidates.length === 1) {
|
|
7604
|
+
const canonical = candidates[0];
|
|
7605
|
+
if (!canonical) continue;
|
|
7606
|
+
const relative = path49.relative(root, canonical.file).replaceAll(path49.sep, "/");
|
|
7607
|
+
context.report({
|
|
7608
|
+
node,
|
|
7609
|
+
loc: { line: use.line, column: use.column },
|
|
7610
|
+
message: `Reuse ${canonicalName(canonical)} from src/${relative} instead of raw ${formatValue(use)}. ${DOC6}`
|
|
7611
|
+
});
|
|
7612
|
+
continue;
|
|
7613
|
+
}
|
|
7614
|
+
if (candidates.length > 1) continue;
|
|
7615
|
+
const key = `${use.kind}\0${String(use.value)}\0${use.role}`;
|
|
7616
|
+
const peers = groups.get(key) ?? [];
|
|
7617
|
+
if (peers.length < 2) continue;
|
|
7618
|
+
if (use.kind === "number" && !use.family.startsWith("timer")) continue;
|
|
7619
|
+
context.report({
|
|
7620
|
+
node,
|
|
7621
|
+
loc: { line: use.line, column: use.column },
|
|
7622
|
+
message: messageFor(use, peers, duplicatedApiRoutes, existingRouteEnum, root)
|
|
7148
7623
|
});
|
|
7149
7624
|
}
|
|
7150
7625
|
}
|
|
@@ -7334,7 +7809,7 @@ var repeatedStructureRule = {
|
|
|
7334
7809
|
|
|
7335
7810
|
// eslint/rules/require-barrel-star-exports.ts
|
|
7336
7811
|
import fs5 from "fs";
|
|
7337
|
-
import
|
|
7812
|
+
import path50 from "path";
|
|
7338
7813
|
var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
|
|
7339
7814
|
var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
|
|
7340
7815
|
var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
@@ -7342,9 +7817,9 @@ function resolveSiblingModule(indexFile, specifier) {
|
|
|
7342
7817
|
if (!specifier.startsWith("./")) return void 0;
|
|
7343
7818
|
const relative = specifier.slice(2);
|
|
7344
7819
|
if (!relative || relative.includes("/")) return void 0;
|
|
7345
|
-
const directory =
|
|
7346
|
-
const direct =
|
|
7347
|
-
const candidates =
|
|
7820
|
+
const directory = path50.dirname(indexFile);
|
|
7821
|
+
const direct = path50.resolve(directory, relative);
|
|
7822
|
+
const candidates = path50.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
|
|
7348
7823
|
return candidates.find((candidate) => fs5.existsSync(candidate) && fs5.statSync(candidate).isFile());
|
|
7349
7824
|
}
|
|
7350
7825
|
var requireBarrelStarExportsRule = {
|
|
@@ -7357,9 +7832,9 @@ var requireBarrelStarExportsRule = {
|
|
|
7357
7832
|
fixable: "code"
|
|
7358
7833
|
},
|
|
7359
7834
|
create(context) {
|
|
7360
|
-
const filename =
|
|
7361
|
-
if (!INDEX_NAMES.has(
|
|
7362
|
-
if (!SUPPORT_FOLDERS3.has(
|
|
7835
|
+
const filename = path50.resolve(context.filename);
|
|
7836
|
+
if (!INDEX_NAMES.has(path50.basename(filename))) return {};
|
|
7837
|
+
if (!SUPPORT_FOLDERS3.has(path50.basename(path50.dirname(filename)))) return {};
|
|
7363
7838
|
return {
|
|
7364
7839
|
ExportNamedDeclaration(node) {
|
|
7365
7840
|
const sourceNode = node.source;
|
|
@@ -7412,7 +7887,7 @@ var requireBarrelStarExportsRule = {
|
|
|
7412
7887
|
};
|
|
7413
7888
|
|
|
7414
7889
|
// eslint/rules/root-support-placement.ts
|
|
7415
|
-
import
|
|
7890
|
+
import path51 from "path";
|
|
7416
7891
|
function isSupportFolder(value) {
|
|
7417
7892
|
return value === "utils" || value === "types" || value === "schemas" || value === "constants";
|
|
7418
7893
|
}
|
|
@@ -7445,7 +7920,7 @@ var rootSupportPlacementRule = {
|
|
|
7445
7920
|
},
|
|
7446
7921
|
create(context) {
|
|
7447
7922
|
const sourceRoot = sourceRootOf(context);
|
|
7448
|
-
const file =
|
|
7923
|
+
const file = path51.resolve(context.filename);
|
|
7449
7924
|
const segments = segmentsOf(file, sourceRoot);
|
|
7450
7925
|
const folderSegments = folderSegmentsOf(file, sourceRoot);
|
|
7451
7926
|
const supportFolder = folderSegments[folderSegments.length - 1];
|
|
@@ -7491,8 +7966,8 @@ var rootSupportPlacementRule = {
|
|
|
7491
7966
|
};
|
|
7492
7967
|
|
|
7493
7968
|
// eslint/rules/route-handler-shape.ts
|
|
7494
|
-
import
|
|
7495
|
-
import
|
|
7969
|
+
import path52 from "path";
|
|
7970
|
+
import ts12 from "typescript";
|
|
7496
7971
|
var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
7497
7972
|
var REQUIRED_BOUNDARY = "withResponse";
|
|
7498
7973
|
function isFunctionLike(node) {
|
|
@@ -7510,33 +7985,33 @@ function findHandler(node) {
|
|
|
7510
7985
|
return void 0;
|
|
7511
7986
|
}
|
|
7512
7987
|
function isLoop(node) {
|
|
7513
|
-
return
|
|
7988
|
+
return ts12.isForStatement(node) || ts12.isForOfStatement(node) || ts12.isForInStatement(node) || ts12.isWhileStatement(node) || ts12.isDoStatement(node);
|
|
7514
7989
|
}
|
|
7515
7990
|
function isFunctionBoundary(node) {
|
|
7516
|
-
return
|
|
7991
|
+
return ts12.isFunctionExpression(node) || ts12.isArrowFunction(node) || ts12.isFunctionDeclaration(node);
|
|
7517
7992
|
}
|
|
7518
7993
|
function analyzeHandlerBody(body, sourceText) {
|
|
7519
7994
|
const start = body.range?.[0] ?? 0;
|
|
7520
7995
|
const end = body.range?.[1] ?? sourceText.length;
|
|
7521
|
-
const sourceFile =
|
|
7996
|
+
const sourceFile = ts12.createSourceFile(
|
|
7522
7997
|
"route.ts",
|
|
7523
7998
|
sourceText.slice(start, end),
|
|
7524
|
-
|
|
7999
|
+
ts12.ScriptTarget.Latest,
|
|
7525
8000
|
true,
|
|
7526
|
-
|
|
8001
|
+
ts12.ScriptKind.TS
|
|
7527
8002
|
);
|
|
7528
8003
|
const kinds = /* @__PURE__ */ new Set();
|
|
7529
8004
|
const calledNames = /* @__PURE__ */ new Set();
|
|
7530
8005
|
const visit = (node) => {
|
|
7531
|
-
if (
|
|
8006
|
+
if (ts12.isTryStatement(node)) kinds.add("try");
|
|
7532
8007
|
if (isLoop(node)) kinds.add("loop");
|
|
7533
|
-
if (
|
|
7534
|
-
if (
|
|
8008
|
+
if (ts12.isIfStatement(node)) kinds.add("if");
|
|
8009
|
+
if (ts12.isCallExpression(node) && ts12.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
|
|
7535
8010
|
kinds.add("map");
|
|
7536
8011
|
}
|
|
7537
|
-
if (
|
|
8012
|
+
if (ts12.isCallExpression(node) && ts12.isIdentifier(node.expression)) calledNames.add(node.expression.text);
|
|
7538
8013
|
if (isFunctionBoundary(node)) return;
|
|
7539
|
-
|
|
8014
|
+
ts12.forEachChild(node, visit);
|
|
7540
8015
|
};
|
|
7541
8016
|
visit(sourceFile);
|
|
7542
8017
|
return { kinds, calledNames };
|
|
@@ -7576,7 +8051,7 @@ var routeHandlerShapeRule = {
|
|
|
7576
8051
|
}
|
|
7577
8052
|
},
|
|
7578
8053
|
create(context) {
|
|
7579
|
-
if (
|
|
8054
|
+
if (path52.basename(context.filename) !== "route.ts") return {};
|
|
7580
8055
|
const sourceText = context.sourceCode.text;
|
|
7581
8056
|
function reportUnwrapped(node, name) {
|
|
7582
8057
|
context.report({
|
|
@@ -7635,7 +8110,7 @@ var routeHandlerShapeRule = {
|
|
|
7635
8110
|
};
|
|
7636
8111
|
|
|
7637
8112
|
// eslint/rules/schema-casing.ts
|
|
7638
|
-
import
|
|
8113
|
+
import path53 from "path";
|
|
7639
8114
|
function isCamelCase(name) {
|
|
7640
8115
|
return /^[a-z][a-zA-Z0-9]*$/.test(name);
|
|
7641
8116
|
}
|
|
@@ -7663,9 +8138,9 @@ var schemaCasingRule = {
|
|
|
7663
8138
|
}
|
|
7664
8139
|
},
|
|
7665
8140
|
create(context) {
|
|
7666
|
-
const filename =
|
|
8141
|
+
const filename = path53.resolve(context.filename);
|
|
7667
8142
|
const sourceRoot = sourceRootOf(context);
|
|
7668
|
-
if (!filename.startsWith(sourceRoot +
|
|
8143
|
+
if (!filename.startsWith(sourceRoot + path53.sep)) return {};
|
|
7669
8144
|
let zodLocalName;
|
|
7670
8145
|
return {
|
|
7671
8146
|
ImportDeclaration(node) {
|
|
@@ -7697,39 +8172,39 @@ var schemaCasingRule = {
|
|
|
7697
8172
|
};
|
|
7698
8173
|
|
|
7699
8174
|
// eslint/rules/sole-state-owner.ts
|
|
7700
|
-
import
|
|
7701
|
-
import
|
|
8175
|
+
import path54 from "path";
|
|
8176
|
+
import ts13 from "typescript";
|
|
7702
8177
|
function findStateHooks(node) {
|
|
7703
8178
|
const hooks = [];
|
|
7704
8179
|
const visit = (child) => {
|
|
7705
|
-
if (
|
|
7706
|
-
if (
|
|
8180
|
+
if (ts13.isCallExpression(child) && ts13.isIdentifier(child.expression) && child.expression.text === "useState") {
|
|
8181
|
+
if (ts13.isVariableDeclaration(child.parent)) {
|
|
7707
8182
|
const { name } = child.parent;
|
|
7708
|
-
if (
|
|
8183
|
+
if (ts13.isArrayBindingPattern(name) && name.elements.length >= 2) {
|
|
7709
8184
|
const value = name.elements[0];
|
|
7710
8185
|
const updater = name.elements[1];
|
|
7711
|
-
if (value && updater &&
|
|
8186
|
+
if (value && updater && ts13.isBindingElement(value) && ts13.isBindingElement(updater)) {
|
|
7712
8187
|
const valueName = value.name;
|
|
7713
8188
|
const updaterName = updater.name;
|
|
7714
|
-
if (
|
|
8189
|
+
if (ts13.isIdentifier(valueName) && ts13.isIdentifier(updaterName)) {
|
|
7715
8190
|
hooks.push({ value: valueName.text, updater: updaterName.text });
|
|
7716
8191
|
}
|
|
7717
8192
|
}
|
|
7718
8193
|
}
|
|
7719
8194
|
}
|
|
7720
8195
|
}
|
|
7721
|
-
|
|
8196
|
+
ts13.forEachChild(child, visit);
|
|
7722
8197
|
};
|
|
7723
8198
|
visit(node);
|
|
7724
8199
|
return hooks;
|
|
7725
8200
|
}
|
|
7726
8201
|
function isHookUsage(node, hook) {
|
|
7727
|
-
if (
|
|
8202
|
+
if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression) && node.expression.text === hook.updater) {
|
|
7728
8203
|
return "updater";
|
|
7729
8204
|
}
|
|
7730
|
-
if (
|
|
8205
|
+
if (ts13.isIdentifier(node) && node.text === hook.value) {
|
|
7731
8206
|
const parent = node.parent;
|
|
7732
|
-
if (
|
|
8207
|
+
if (ts13.isBindingElement(parent) || ts13.isPropertyAccessExpression(parent) || ts13.isShorthandPropertyAssignment(parent)) {
|
|
7733
8208
|
return void 0;
|
|
7734
8209
|
}
|
|
7735
8210
|
return "value";
|
|
@@ -7739,16 +8214,16 @@ function isHookUsage(node, hook) {
|
|
|
7739
8214
|
function topLevelJsxChildren(initial) {
|
|
7740
8215
|
if (!initial) return void 0;
|
|
7741
8216
|
let expression = initial;
|
|
7742
|
-
while (
|
|
7743
|
-
if (
|
|
8217
|
+
while (ts13.isParenthesizedExpression(expression)) expression = expression.expression;
|
|
8218
|
+
if (ts13.isJsxFragment(expression)) {
|
|
7744
8219
|
const children = expression.children.filter(
|
|
7745
|
-
(c) => !
|
|
8220
|
+
(c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
|
|
7746
8221
|
);
|
|
7747
8222
|
return { root: expression, children };
|
|
7748
8223
|
}
|
|
7749
|
-
if (
|
|
8224
|
+
if (ts13.isJsxElement(expression)) {
|
|
7750
8225
|
const children = expression.children.filter(
|
|
7751
|
-
(c) => !
|
|
8226
|
+
(c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
|
|
7752
8227
|
);
|
|
7753
8228
|
return { root: expression, children };
|
|
7754
8229
|
}
|
|
@@ -7762,8 +8237,8 @@ function collectUsesIn(child, hook) {
|
|
|
7762
8237
|
positions.push(node);
|
|
7763
8238
|
count += 1;
|
|
7764
8239
|
}
|
|
7765
|
-
if (
|
|
7766
|
-
|
|
8240
|
+
if (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node)) return;
|
|
8241
|
+
ts13.forEachChild(node, visit);
|
|
7767
8242
|
};
|
|
7768
8243
|
visit(child);
|
|
7769
8244
|
return { positions, count };
|
|
@@ -7777,7 +8252,7 @@ var soleStateOwnerRule = {
|
|
|
7777
8252
|
}
|
|
7778
8253
|
},
|
|
7779
8254
|
create(context) {
|
|
7780
|
-
const filename =
|
|
8255
|
+
const filename = path54.resolve(context.filename);
|
|
7781
8256
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
7782
8257
|
const text = context.sourceCode.text;
|
|
7783
8258
|
const components = parseComponentInfo(text, filename);
|
|
@@ -7802,18 +8277,18 @@ var soleStateOwnerRule = {
|
|
|
7802
8277
|
}
|
|
7803
8278
|
};
|
|
7804
8279
|
function analyzeSoleOwner(declaration, hook) {
|
|
7805
|
-
const body =
|
|
7806
|
-
if (!body || !
|
|
8280
|
+
const body = ts13.isFunctionDeclaration(declaration) ? declaration.body : void 0;
|
|
8281
|
+
if (!body || !ts13.isBlock(body)) return void 0;
|
|
7807
8282
|
const returns = [];
|
|
7808
8283
|
const visit = (node) => {
|
|
7809
|
-
if (node !== body && (
|
|
7810
|
-
if (
|
|
7811
|
-
|
|
8284
|
+
if (node !== body && (ts13.isFunctionLike(node) || ts13.isClassLike(node))) return;
|
|
8285
|
+
if (ts13.isReturnStatement(node)) returns.push(node);
|
|
8286
|
+
ts13.forEachChild(node, visit);
|
|
7812
8287
|
};
|
|
7813
8288
|
visit(body);
|
|
7814
8289
|
if (returns.length !== 1) return void 0;
|
|
7815
8290
|
const single = returns[0];
|
|
7816
|
-
if (!single?.expression || !
|
|
8291
|
+
if (!single?.expression || !ts13.isExpression(single.expression)) return void 0;
|
|
7817
8292
|
const returnExpression = single.expression;
|
|
7818
8293
|
const root = topLevelJsxChildren(returnExpression);
|
|
7819
8294
|
if (!root || root.children.length === 0) return void 0;
|
|
@@ -7836,11 +8311,11 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
7836
8311
|
let outside = false;
|
|
7837
8312
|
const visit = (node) => {
|
|
7838
8313
|
if (outside) return;
|
|
7839
|
-
if (node !== declaration && (
|
|
8314
|
+
if (node !== declaration && (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node))) return;
|
|
7840
8315
|
if (isHookUsage(node, hook)) {
|
|
7841
8316
|
let current = node;
|
|
7842
8317
|
let isInJsxChild = false;
|
|
7843
|
-
while (!
|
|
8318
|
+
while (!ts13.isSourceFile(current)) {
|
|
7844
8319
|
if (children.includes(current)) {
|
|
7845
8320
|
isInJsxChild = true;
|
|
7846
8321
|
break;
|
|
@@ -7849,14 +8324,14 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
7849
8324
|
}
|
|
7850
8325
|
if (!isInJsxChild) outside = true;
|
|
7851
8326
|
}
|
|
7852
|
-
|
|
8327
|
+
ts13.forEachChild(node, visit);
|
|
7853
8328
|
};
|
|
7854
8329
|
visit(declaration);
|
|
7855
8330
|
return outside;
|
|
7856
8331
|
}
|
|
7857
8332
|
|
|
7858
8333
|
// eslint/rules/source-under-src.ts
|
|
7859
|
-
import
|
|
8334
|
+
import path55 from "path";
|
|
7860
8335
|
var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
|
|
7861
8336
|
".agents",
|
|
7862
8337
|
".cache",
|
|
@@ -7897,14 +8372,14 @@ var sourceUnderSrcRule = {
|
|
|
7897
8372
|
}
|
|
7898
8373
|
},
|
|
7899
8374
|
create(context) {
|
|
7900
|
-
const filename =
|
|
8375
|
+
const filename = path55.resolve(context.filename);
|
|
7901
8376
|
if (!MODULE_EXTENSION.test(filename)) return {};
|
|
7902
|
-
const relative =
|
|
8377
|
+
const relative = path55.relative(context.cwd, filename).replace(/\\/g, "/");
|
|
7903
8378
|
if (relative === "src" || relative.startsWith("src/")) return {};
|
|
7904
8379
|
const topLevel = relative.split("/")[0] ?? "";
|
|
7905
8380
|
if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
|
|
7906
8381
|
if (!relative.includes("/")) {
|
|
7907
|
-
const basename =
|
|
8382
|
+
const basename = path55.basename(filename);
|
|
7908
8383
|
if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
|
|
7909
8384
|
}
|
|
7910
8385
|
return {
|
|
@@ -7920,7 +8395,7 @@ var sourceUnderSrcRule = {
|
|
|
7920
8395
|
};
|
|
7921
8396
|
|
|
7922
8397
|
// eslint/rules/stay-flat.ts
|
|
7923
|
-
import
|
|
8398
|
+
import path56 from "path";
|
|
7924
8399
|
var stayFlatRule = {
|
|
7925
8400
|
meta: {
|
|
7926
8401
|
schema: [],
|
|
@@ -7931,7 +8406,7 @@ var stayFlatRule = {
|
|
|
7931
8406
|
},
|
|
7932
8407
|
create(context) {
|
|
7933
8408
|
const sourceRoot = sourceRootOf(context);
|
|
7934
|
-
const file =
|
|
8409
|
+
const file = path56.resolve(context.filename);
|
|
7935
8410
|
const segments = segmentsOf(file, sourceRoot);
|
|
7936
8411
|
if (segments.length !== 3 || segments[0] !== "features") return {};
|
|
7937
8412
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -7971,7 +8446,7 @@ var stayFlatRule = {
|
|
|
7971
8446
|
};
|
|
7972
8447
|
|
|
7973
8448
|
// eslint/rules/support-file-placement.ts
|
|
7974
|
-
import
|
|
8449
|
+
import path57 from "path";
|
|
7975
8450
|
var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
|
|
7976
8451
|
var EXPORT_KIND_BY_SUPPORT_FOLDER = /* @__PURE__ */ new Map([
|
|
7977
8452
|
["constants", "constant"],
|
|
@@ -7996,7 +8471,7 @@ var supportFilePlacementRule = {
|
|
|
7996
8471
|
},
|
|
7997
8472
|
create(context) {
|
|
7998
8473
|
const sourceRoot = sourceRootOf(context);
|
|
7999
|
-
const supportFile =
|
|
8474
|
+
const supportFile = path57.resolve(context.filename);
|
|
8000
8475
|
const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
|
|
8001
8476
|
const supportFolder = currentFolder[currentFolder.length - 1];
|
|
8002
8477
|
if (supportFolder === void 0 || !SUPPORT_FOLDERS.has(supportFolder)) return {};
|
|
@@ -8050,7 +8525,7 @@ var supportFilePlacementRule = {
|
|
|
8050
8525
|
|
|
8051
8526
|
// eslint/rules/support-folder-shape.ts
|
|
8052
8527
|
import fs6 from "fs";
|
|
8053
|
-
import
|
|
8528
|
+
import path58 from "path";
|
|
8054
8529
|
var SUPPORT_FOLDERS4 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
|
|
8055
8530
|
var INDEX_NAMES2 = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
|
|
8056
8531
|
var supportFolderShapeRule = {
|
|
@@ -8062,12 +8537,12 @@ var supportFolderShapeRule = {
|
|
|
8062
8537
|
}
|
|
8063
8538
|
},
|
|
8064
8539
|
create(context) {
|
|
8065
|
-
const filename =
|
|
8066
|
-
const baseName =
|
|
8540
|
+
const filename = path58.resolve(context.filename);
|
|
8541
|
+
const baseName = path58.basename(filename);
|
|
8067
8542
|
if (!INDEX_NAMES2.has(baseName)) return {};
|
|
8068
|
-
const folder =
|
|
8543
|
+
const folder = path58.basename(path58.dirname(filename));
|
|
8069
8544
|
if (!SUPPORT_FOLDERS4.has(folder)) return {};
|
|
8070
|
-
const directory =
|
|
8545
|
+
const directory = path58.dirname(filename);
|
|
8071
8546
|
let entries;
|
|
8072
8547
|
try {
|
|
8073
8548
|
entries = fs6.readdirSync(directory);
|
|
@@ -8085,7 +8560,7 @@ var supportFolderShapeRule = {
|
|
|
8085
8560
|
for (const match of source.matchAll(exportPattern)) {
|
|
8086
8561
|
hasAnyReExport = true;
|
|
8087
8562
|
const specifier = match.groups?.specifier;
|
|
8088
|
-
if (specifier?.startsWith(".")) exportedFiles.add(
|
|
8563
|
+
if (specifier?.startsWith(".")) exportedFiles.add(path58.basename(specifier));
|
|
8089
8564
|
}
|
|
8090
8565
|
const guide = `docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`;
|
|
8091
8566
|
if (siblingModules.length === 0) {
|
|
@@ -8264,11 +8739,11 @@ var baseLayerPairRule = {
|
|
|
8264
8739
|
|
|
8265
8740
|
// eslint/rules/tailwind/css-entry-point.ts
|
|
8266
8741
|
import { statSync as statSync4 } from "fs";
|
|
8267
|
-
import
|
|
8742
|
+
import path61 from "path";
|
|
8268
8743
|
|
|
8269
8744
|
// eslint/rules/tailwind/source-files.ts
|
|
8270
|
-
import { readdirSync as readdirSync3, readFileSync as
|
|
8271
|
-
import
|
|
8745
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
|
|
8746
|
+
import path59 from "path";
|
|
8272
8747
|
var CSS_EXTENSIONS = [".css"];
|
|
8273
8748
|
var MODULE_EXTENSIONS4 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
8274
8749
|
var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS4, ...CSS_EXTENSIONS];
|
|
@@ -8281,7 +8756,7 @@ function findFiles(dir, extensions) {
|
|
|
8281
8756
|
}
|
|
8282
8757
|
return entries.flatMap((entry) => {
|
|
8283
8758
|
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
8284
|
-
const entryPath =
|
|
8759
|
+
const entryPath = path59.join(dir, entry);
|
|
8285
8760
|
let stats;
|
|
8286
8761
|
try {
|
|
8287
8762
|
stats = statSync3(entryPath);
|
|
@@ -8289,7 +8764,7 @@ function findFiles(dir, extensions) {
|
|
|
8289
8764
|
return [];
|
|
8290
8765
|
}
|
|
8291
8766
|
if (stats.isDirectory()) return findFiles(entryPath, extensions);
|
|
8292
|
-
return extensions.includes(
|
|
8767
|
+
return extensions.includes(path59.extname(entry)) ? [entryPath] : [];
|
|
8293
8768
|
});
|
|
8294
8769
|
}
|
|
8295
8770
|
function cachedTextReader() {
|
|
@@ -8298,7 +8773,7 @@ function cachedTextReader() {
|
|
|
8298
8773
|
let text = texts.get(file);
|
|
8299
8774
|
if (text === void 0) {
|
|
8300
8775
|
try {
|
|
8301
|
-
text =
|
|
8776
|
+
text = readFileSync11(file, "utf8");
|
|
8302
8777
|
} catch {
|
|
8303
8778
|
text = "";
|
|
8304
8779
|
}
|
|
@@ -8312,7 +8787,7 @@ function escapeRegExp(text) {
|
|
|
8312
8787
|
}
|
|
8313
8788
|
|
|
8314
8789
|
// eslint/rules/tailwind/stylesheet-graph.ts
|
|
8315
|
-
import
|
|
8790
|
+
import path60 from "path";
|
|
8316
8791
|
function registersTailwind(text) {
|
|
8317
8792
|
return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
|
|
8318
8793
|
}
|
|
@@ -8326,25 +8801,25 @@ function moduleImports(text, fileName) {
|
|
|
8326
8801
|
return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
|
|
8327
8802
|
}
|
|
8328
8803
|
function resolveSpecifier2(fromFile, spec, sourceRoot) {
|
|
8329
|
-
if (spec.startsWith("/")) return
|
|
8330
|
-
if (spec.startsWith("./") || spec.startsWith("../")) return
|
|
8331
|
-
if (spec.startsWith("@/")) return
|
|
8804
|
+
if (spec.startsWith("/")) return path60.resolve(spec);
|
|
8805
|
+
if (spec.startsWith("./") || spec.startsWith("../")) return path60.resolve(path60.dirname(fromFile), spec);
|
|
8806
|
+
if (spec.startsWith("@/")) return path60.resolve(sourceRoot, spec.slice(2));
|
|
8332
8807
|
return void 0;
|
|
8333
8808
|
}
|
|
8334
8809
|
function buildStylesheetGraph(options) {
|
|
8335
8810
|
const { cssFiles, sourceRoot, textOf } = options;
|
|
8336
|
-
const cssSet = new Set(cssFiles.map((file) =>
|
|
8811
|
+
const cssSet = new Set(cssFiles.map((file) => path60.normalize(file)));
|
|
8337
8812
|
const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
|
|
8338
8813
|
const reachable = /* @__PURE__ */ new Set();
|
|
8339
8814
|
const queue = [...globals];
|
|
8340
|
-
for (const global of globals) reachable.add(
|
|
8815
|
+
for (const global of globals) reachable.add(path60.normalize(global));
|
|
8341
8816
|
while (queue.length > 0) {
|
|
8342
8817
|
const from = queue.shift();
|
|
8343
8818
|
if (!from) continue;
|
|
8344
8819
|
for (const spec of importedSpecifiers(textOf(from))) {
|
|
8345
8820
|
const target = resolveSpecifier2(from, spec, sourceRoot);
|
|
8346
8821
|
if (!target) continue;
|
|
8347
|
-
const normalized =
|
|
8822
|
+
const normalized = path60.normalize(target);
|
|
8348
8823
|
if (cssSet.has(normalized) && !reachable.has(normalized)) {
|
|
8349
8824
|
reachable.add(normalized);
|
|
8350
8825
|
queue.push(normalized);
|
|
@@ -8356,7 +8831,7 @@ function buildStylesheetGraph(options) {
|
|
|
8356
8831
|
for (const spec of importedSpecifiers(textOf(global))) {
|
|
8357
8832
|
const target = resolveSpecifier2(global, spec, sourceRoot);
|
|
8358
8833
|
if (!target) continue;
|
|
8359
|
-
const normalized =
|
|
8834
|
+
const normalized = path60.normalize(target);
|
|
8360
8835
|
if (cssSet.has(normalized)) directChildren.add(normalized);
|
|
8361
8836
|
}
|
|
8362
8837
|
}
|
|
@@ -8364,8 +8839,8 @@ function buildStylesheetGraph(options) {
|
|
|
8364
8839
|
}
|
|
8365
8840
|
|
|
8366
8841
|
// eslint/rules/tailwind/css-entry-point.ts
|
|
8367
|
-
var APP_STYLES_DIR =
|
|
8368
|
-
var GLOBAL_STYLESHEET_PATH =
|
|
8842
|
+
var APP_STYLES_DIR = path61.join("app", "styles");
|
|
8843
|
+
var GLOBAL_STYLESHEET_PATH = path61.join(APP_STYLES_DIR, "globals.css");
|
|
8369
8844
|
var cssEntryPointRule = {
|
|
8370
8845
|
meta: {
|
|
8371
8846
|
schema: [],
|
|
@@ -8391,8 +8866,8 @@ var cssEntryPointRule = {
|
|
|
8391
8866
|
return {
|
|
8392
8867
|
"StyleSheet:exit"(node) {
|
|
8393
8868
|
if (globals.length === 0) return;
|
|
8394
|
-
const current =
|
|
8395
|
-
const relative =
|
|
8869
|
+
const current = path61.normalize(path61.resolve(context.filename));
|
|
8870
|
+
const relative = path61.relative(sourceRoot, current);
|
|
8396
8871
|
if (globals.includes(current)) {
|
|
8397
8872
|
if (globals.length > 1) {
|
|
8398
8873
|
context.report({
|
|
@@ -8408,7 +8883,7 @@ var cssEntryPointRule = {
|
|
|
8408
8883
|
});
|
|
8409
8884
|
return;
|
|
8410
8885
|
}
|
|
8411
|
-
const basename =
|
|
8886
|
+
const basename = path61.basename(current);
|
|
8412
8887
|
const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
|
|
8413
8888
|
if (importCount !== 1) {
|
|
8414
8889
|
context.report({
|
|
@@ -8418,7 +8893,7 @@ var cssEntryPointRule = {
|
|
|
8418
8893
|
}
|
|
8419
8894
|
return;
|
|
8420
8895
|
}
|
|
8421
|
-
const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${
|
|
8896
|
+
const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path61.sep}`);
|
|
8422
8897
|
if (!isInAppStyles) {
|
|
8423
8898
|
context.report({
|
|
8424
8899
|
node,
|
|
@@ -8907,7 +9382,7 @@ var tailwindRules = {
|
|
|
8907
9382
|
};
|
|
8908
9383
|
|
|
8909
9384
|
// eslint/rules/type-extraction.ts
|
|
8910
|
-
import
|
|
9385
|
+
import path62 from "path";
|
|
8911
9386
|
var typeExtractionRule = {
|
|
8912
9387
|
meta: {
|
|
8913
9388
|
schema: [],
|
|
@@ -8918,7 +9393,7 @@ var typeExtractionRule = {
|
|
|
8918
9393
|
},
|
|
8919
9394
|
create(context) {
|
|
8920
9395
|
const sourceRoot = sourceRootOf(context);
|
|
8921
|
-
const file =
|
|
9396
|
+
const file = path62.resolve(context.filename);
|
|
8922
9397
|
const segments = segmentsOf(file, sourceRoot);
|
|
8923
9398
|
if (segments.length === 0) return {};
|
|
8924
9399
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -9057,9 +9532,9 @@ var uiStateRule = {
|
|
|
9057
9532
|
};
|
|
9058
9533
|
|
|
9059
9534
|
// eslint/rules/unknown-utility.ts
|
|
9060
|
-
import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as
|
|
9535
|
+
import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync6 } from "fs";
|
|
9061
9536
|
import { createRequire } from "module";
|
|
9062
|
-
import
|
|
9537
|
+
import path63 from "path";
|
|
9063
9538
|
var PREFIX_NAMESPACES = {
|
|
9064
9539
|
bg: ["color"],
|
|
9065
9540
|
text: ["color", "text"],
|
|
@@ -9299,7 +9774,7 @@ function stylesheetFiles(dir) {
|
|
|
9299
9774
|
}
|
|
9300
9775
|
return entries.flatMap((entry) => {
|
|
9301
9776
|
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
9302
|
-
const entryPath =
|
|
9777
|
+
const entryPath = path63.join(dir, entry);
|
|
9303
9778
|
let stats;
|
|
9304
9779
|
try {
|
|
9305
9780
|
stats = statSync6(entryPath);
|
|
@@ -9307,7 +9782,7 @@ function stylesheetFiles(dir) {
|
|
|
9307
9782
|
return [];
|
|
9308
9783
|
}
|
|
9309
9784
|
if (stats.isDirectory()) return stylesheetFiles(entryPath);
|
|
9310
|
-
return
|
|
9785
|
+
return path63.extname(entry) === ".css" ? [entryPath] : [];
|
|
9311
9786
|
});
|
|
9312
9787
|
}
|
|
9313
9788
|
function packageNameOf(specifier) {
|
|
@@ -9318,24 +9793,24 @@ function packageNameOf(specifier) {
|
|
|
9318
9793
|
function resolvePackageStylesheet(fromFile, specifier) {
|
|
9319
9794
|
const packageName = packageNameOf(specifier);
|
|
9320
9795
|
if (!packageName || packageName === "tailwindcss") return void 0;
|
|
9321
|
-
let directory =
|
|
9322
|
-
while (directory !==
|
|
9323
|
-
const packageRoot =
|
|
9324
|
-
const manifestPath =
|
|
9796
|
+
let directory = path63.dirname(fromFile);
|
|
9797
|
+
while (directory !== path63.dirname(directory)) {
|
|
9798
|
+
const packageRoot = path63.join(directory, "node_modules", packageName);
|
|
9799
|
+
const manifestPath = path63.join(packageRoot, "package.json");
|
|
9325
9800
|
if (existsSync6(manifestPath)) {
|
|
9326
9801
|
try {
|
|
9327
|
-
const manifest =
|
|
9802
|
+
const manifest = readFileSync12(manifestPath, "utf8");
|
|
9328
9803
|
const stylesheet = /"style"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
|
|
9329
9804
|
const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
|
|
9330
9805
|
const target = stylesheet ?? main;
|
|
9331
9806
|
if (!target) return void 0;
|
|
9332
|
-
const resolved =
|
|
9807
|
+
const resolved = path63.resolve(packageRoot, target);
|
|
9333
9808
|
return existsSync6(resolved) ? resolved : void 0;
|
|
9334
9809
|
} catch {
|
|
9335
9810
|
return void 0;
|
|
9336
9811
|
}
|
|
9337
9812
|
}
|
|
9338
|
-
directory =
|
|
9813
|
+
directory = path63.dirname(directory);
|
|
9339
9814
|
}
|
|
9340
9815
|
return void 0;
|
|
9341
9816
|
}
|
|
@@ -9344,7 +9819,7 @@ function inventoryStylesheetFiles(projectFiles) {
|
|
|
9344
9819
|
for (const file of projectFiles) {
|
|
9345
9820
|
let css2;
|
|
9346
9821
|
try {
|
|
9347
|
-
css2 =
|
|
9822
|
+
css2 = readFileSync12(file, "utf8");
|
|
9348
9823
|
} catch {
|
|
9349
9824
|
continue;
|
|
9350
9825
|
}
|
|
@@ -9410,7 +9885,7 @@ function readInventory(files) {
|
|
|
9410
9885
|
for (const file of files) {
|
|
9411
9886
|
let css2;
|
|
9412
9887
|
try {
|
|
9413
|
-
css2 =
|
|
9888
|
+
css2 = readFileSync12(file, "utf8");
|
|
9414
9889
|
} catch {
|
|
9415
9890
|
continue;
|
|
9416
9891
|
}
|
|
@@ -9586,7 +10061,7 @@ var unknownUtilityRule = {
|
|
|
9586
10061
|
};
|
|
9587
10062
|
|
|
9588
10063
|
// eslint/rules/util-file-name.ts
|
|
9589
|
-
import
|
|
10064
|
+
import path64 from "path";
|
|
9590
10065
|
function toKebabCase2(value) {
|
|
9591
10066
|
return value.replace(/(?<lower>[a-z0-9])(?<upper>[A-Z])/g, "$<lower>-$<upper>").replace(/(?<first>[A-Z])(?<rest>[A-Z][a-z])/g, "$<first>-$<rest>").toLowerCase();
|
|
9592
10067
|
}
|
|
@@ -9599,7 +10074,7 @@ var utilFileNameRule = {
|
|
|
9599
10074
|
}
|
|
9600
10075
|
},
|
|
9601
10076
|
create(context) {
|
|
9602
|
-
const filename =
|
|
10077
|
+
const filename = path64.resolve(context.filename);
|
|
9603
10078
|
const segments = filename.replace(/\\/g, "/").split("/");
|
|
9604
10079
|
if (!segments.includes("utils")) return {};
|
|
9605
10080
|
let module;
|
|
@@ -9613,13 +10088,13 @@ var utilFileNameRule = {
|
|
|
9613
10088
|
const functionName = functions[0]?.name;
|
|
9614
10089
|
if (!functionName) return {};
|
|
9615
10090
|
const expected = toKebabCase2(functionName);
|
|
9616
|
-
const actual =
|
|
10091
|
+
const actual = path64.basename(filename, path64.extname(filename));
|
|
9617
10092
|
if (!expected || actual === expected) return {};
|
|
9618
10093
|
return {
|
|
9619
10094
|
Program(node) {
|
|
9620
10095
|
context.report({
|
|
9621
10096
|
node,
|
|
9622
|
-
message: `A utility file exporting ${functionName} must be named ${expected}.${
|
|
10097
|
+
message: `A utility file exporting ${functionName} must be named ${expected}.${path64.extname(filename).slice(1)}.`
|
|
9623
10098
|
});
|
|
9624
10099
|
}
|
|
9625
10100
|
};
|
|
@@ -9627,7 +10102,7 @@ var utilFileNameRule = {
|
|
|
9627
10102
|
};
|
|
9628
10103
|
|
|
9629
10104
|
// eslint/rules/value-extraction.ts
|
|
9630
|
-
import
|
|
10105
|
+
import path65 from "path";
|
|
9631
10106
|
var valueExtractionRule = {
|
|
9632
10107
|
meta: {
|
|
9633
10108
|
schema: [],
|
|
@@ -9638,7 +10113,7 @@ var valueExtractionRule = {
|
|
|
9638
10113
|
},
|
|
9639
10114
|
create(context) {
|
|
9640
10115
|
const sourceRoot = sourceRootOf(context);
|
|
9641
|
-
const file =
|
|
10116
|
+
const file = path65.resolve(context.filename);
|
|
9642
10117
|
const segments = segmentsOf(file, sourceRoot);
|
|
9643
10118
|
if (segments.length === 0 || segments[0] !== "app") return {};
|
|
9644
10119
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -9659,8 +10134,8 @@ var valueExtractionRule = {
|
|
|
9659
10134
|
};
|
|
9660
10135
|
|
|
9661
10136
|
// eslint/rules/vulyk/tracked-docs.ts
|
|
9662
|
-
import { existsSync as existsSync7, readFileSync as
|
|
9663
|
-
import
|
|
10137
|
+
import { existsSync as existsSync7, readFileSync as readFileSync13 } from "fs";
|
|
10138
|
+
import path66 from "path";
|
|
9664
10139
|
var PASIKA_REPO = "Bredansky/pasika";
|
|
9665
10140
|
var BASE_REQUIRED_TRACKED_DOCS = [
|
|
9666
10141
|
{ name: "documentation-guide", path: "docs/documentation-guide" },
|
|
@@ -9671,13 +10146,13 @@ var NEXTJS_REQUIRED_TRACKED_DOCS = [
|
|
|
9671
10146
|
{ name: "next-codebase-guide", path: "docs/next-codebase-guide" },
|
|
9672
10147
|
{ name: "next-tailwind-guide", path: "docs/next-tailwind-guide" }
|
|
9673
10148
|
];
|
|
9674
|
-
function
|
|
10149
|
+
function memberName7(member) {
|
|
9675
10150
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
9676
10151
|
}
|
|
9677
10152
|
function hasDependency(root, name) {
|
|
9678
|
-
const section = root.members.find((member) =>
|
|
10153
|
+
const section = root.members.find((member) => memberName7(member) === "dependencies");
|
|
9679
10154
|
if (section?.value.type !== "Object") return false;
|
|
9680
|
-
return section.value.members.some((member) =>
|
|
10155
|
+
return section.value.members.some((member) => memberName7(member) === name);
|
|
9681
10156
|
}
|
|
9682
10157
|
var trackedDocsRule = {
|
|
9683
10158
|
meta: {
|
|
@@ -9693,8 +10168,8 @@ var trackedDocsRule = {
|
|
|
9693
10168
|
if (!context.filename.endsWith("package.json")) return;
|
|
9694
10169
|
const root = node.body;
|
|
9695
10170
|
if (root.type !== "Object") return;
|
|
9696
|
-
const projectRoot =
|
|
9697
|
-
const configPath =
|
|
10171
|
+
const projectRoot = path66.dirname(path66.resolve(context.filename));
|
|
10172
|
+
const configPath = path66.join(projectRoot, "vulyk.config.ts");
|
|
9698
10173
|
if (!existsSync7(configPath)) {
|
|
9699
10174
|
context.report({
|
|
9700
10175
|
node,
|
|
@@ -9702,7 +10177,7 @@ var trackedDocsRule = {
|
|
|
9702
10177
|
});
|
|
9703
10178
|
return;
|
|
9704
10179
|
}
|
|
9705
|
-
const config =
|
|
10180
|
+
const config = readFileSync13(configPath, "utf8");
|
|
9706
10181
|
if (!config.includes(PASIKA_REPO)) {
|
|
9707
10182
|
context.report({
|
|
9708
10183
|
node,
|
|
@@ -9719,7 +10194,7 @@ var trackedDocsRule = {
|
|
|
9719
10194
|
});
|
|
9720
10195
|
}
|
|
9721
10196
|
}
|
|
9722
|
-
const agentsPath =
|
|
10197
|
+
const agentsPath = path66.join(projectRoot, "AGENTS.md");
|
|
9723
10198
|
if (!existsSync7(agentsPath)) {
|
|
9724
10199
|
context.report({
|
|
9725
10200
|
node,
|
|
@@ -9732,14 +10207,14 @@ var trackedDocsRule = {
|
|
|
9732
10207
|
};
|
|
9733
10208
|
|
|
9734
10209
|
// eslint/rules/vulyk/vulyk-dependency.ts
|
|
9735
|
-
function
|
|
10210
|
+
function memberName8(member) {
|
|
9736
10211
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
9737
10212
|
}
|
|
9738
10213
|
function dependency(root, sectionName) {
|
|
9739
10214
|
if (root.type !== "Object") return void 0;
|
|
9740
|
-
const section = root.members.find((member) =>
|
|
10215
|
+
const section = root.members.find((member) => memberName8(member) === sectionName);
|
|
9741
10216
|
if (section?.value.type !== "Object") return void 0;
|
|
9742
|
-
return section.value.members.find((member) =>
|
|
10217
|
+
return section.value.members.find((member) => memberName8(member) === "vulyk");
|
|
9743
10218
|
}
|
|
9744
10219
|
var vulykDependencyRule = {
|
|
9745
10220
|
meta: {
|
|
@@ -9780,9 +10255,9 @@ var vulykRules = {
|
|
|
9780
10255
|
// eslint/rules/with-response-helper.ts
|
|
9781
10256
|
var HELPER3 = "withResponse";
|
|
9782
10257
|
var ENTRY3 = "pasika/with-response";
|
|
9783
|
-
var
|
|
9784
|
-
var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${
|
|
9785
|
-
var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${
|
|
10258
|
+
var DOC7 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
|
|
10259
|
+
var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC7}`;
|
|
10260
|
+
var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC7}`;
|
|
9786
10261
|
function isNamed3(node, name) {
|
|
9787
10262
|
return node?.type === "Identifier" && node.name === name;
|
|
9788
10263
|
}
|
|
@@ -9819,7 +10294,7 @@ var withResponseHelperRule = {
|
|
|
9819
10294
|
|
|
9820
10295
|
// eslint/rules/zirka-baseline.ts
|
|
9821
10296
|
import fs7 from "fs";
|
|
9822
|
-
import
|
|
10297
|
+
import path67 from "path";
|
|
9823
10298
|
var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
|
|
9824
10299
|
var PRETTIER_CONFIGS = [
|
|
9825
10300
|
"prettier.config.mjs",
|
|
@@ -9838,10 +10313,10 @@ var zirkaBaselineRule = {
|
|
|
9838
10313
|
}
|
|
9839
10314
|
},
|
|
9840
10315
|
create(context) {
|
|
9841
|
-
const filename =
|
|
9842
|
-
const basename =
|
|
10316
|
+
const filename = path67.resolve(context.filename);
|
|
10317
|
+
const basename = path67.basename(filename);
|
|
9843
10318
|
if (!ESLINT_CONFIG.test(basename)) return {};
|
|
9844
|
-
const projectRoot =
|
|
10319
|
+
const projectRoot = path67.dirname(filename);
|
|
9845
10320
|
const report3 = (message) => {
|
|
9846
10321
|
context.report({
|
|
9847
10322
|
node: context.sourceCode.ast,
|
|
@@ -9856,7 +10331,7 @@ var zirkaBaselineRule = {
|
|
|
9856
10331
|
'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
|
|
9857
10332
|
);
|
|
9858
10333
|
}
|
|
9859
|
-
const tsconfigPath =
|
|
10334
|
+
const tsconfigPath = path67.join(projectRoot, "tsconfig.json");
|
|
9860
10335
|
if (!fs7.existsSync(tsconfigPath)) {
|
|
9861
10336
|
report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
|
|
9862
10337
|
} else {
|
|
@@ -9874,13 +10349,13 @@ var zirkaBaselineRule = {
|
|
|
9874
10349
|
report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
|
|
9875
10350
|
}
|
|
9876
10351
|
}
|
|
9877
|
-
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(
|
|
10352
|
+
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path67.join(projectRoot, name)));
|
|
9878
10353
|
if (!prettierConfigFile) {
|
|
9879
10354
|
report3(
|
|
9880
10355
|
"No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
|
|
9881
10356
|
);
|
|
9882
10357
|
} else {
|
|
9883
|
-
const content = fs7.readFileSync(
|
|
10358
|
+
const content = fs7.readFileSync(path67.join(projectRoot, prettierConfigFile), "utf8");
|
|
9884
10359
|
if (!content.includes("zirka")) {
|
|
9885
10360
|
report3(
|
|
9886
10361
|
"The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
|
|
@@ -9903,10 +10378,10 @@ function referencesZirka(sourceCode) {
|
|
|
9903
10378
|
// eslint/rules/zod-fetch-helper.ts
|
|
9904
10379
|
var HELPER4 = "zodFetch";
|
|
9905
10380
|
var ENTRY4 = "pasika/zod-fetch";
|
|
9906
|
-
var
|
|
9907
|
-
var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${
|
|
9908
|
-
var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${
|
|
9909
|
-
var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${
|
|
10381
|
+
var DOC8 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
|
|
10382
|
+
var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${DOC8}`;
|
|
10383
|
+
var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${DOC8}`;
|
|
10384
|
+
var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${DOC8}`;
|
|
9910
10385
|
var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "window", "self", "global"]);
|
|
9911
10386
|
var TEST_FILE2 = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
|
|
9912
10387
|
function isNamed4(node, name) {
|
|
@@ -10026,14 +10501,14 @@ var zodSchemaValidationRule = {
|
|
|
10026
10501
|
};
|
|
10027
10502
|
|
|
10028
10503
|
// eslint/ts-alignment.ts
|
|
10029
|
-
import { readFileSync as
|
|
10504
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
10030
10505
|
import { createRequire as createRequire2 } from "module";
|
|
10031
10506
|
import { join } from "path";
|
|
10032
10507
|
var ownRequire = createRequire2(import.meta.url);
|
|
10033
10508
|
var majorOf = (version) => Number(version.split(".")[0]);
|
|
10034
10509
|
function versionOf(packagePath) {
|
|
10035
10510
|
try {
|
|
10036
|
-
const parsed = JSON.parse(
|
|
10511
|
+
const parsed = JSON.parse(readFileSync14(packagePath, "utf8"));
|
|
10037
10512
|
if (typeof parsed !== "object" || parsed === null || !("version" in parsed)) return null;
|
|
10038
10513
|
return typeof parsed.version === "string" ? parsed.version : null;
|
|
10039
10514
|
} catch {
|
|
@@ -10093,6 +10568,7 @@ var pasikaNextjsAppRules = {
|
|
|
10093
10568
|
"value-extraction": valueExtractionRule,
|
|
10094
10569
|
"constant-casing": constantCasingRule,
|
|
10095
10570
|
"prefer-enum": preferEnumRule,
|
|
10571
|
+
"repeated-semantic-literal": repeatedSemanticLiteralRule,
|
|
10096
10572
|
"prefer-object-destructuring": preferObjectDestructuringRule,
|
|
10097
10573
|
"enum-placement": enumPlacementRule,
|
|
10098
10574
|
"type-extraction": typeExtractionRule,
|
|
@@ -10177,6 +10653,12 @@ var pasikaAppLanguageOptions = {
|
|
|
10177
10653
|
ecmaFeatures: { jsx: true }
|
|
10178
10654
|
}
|
|
10179
10655
|
};
|
|
10656
|
+
var pasikaTypeScriptFileLengthConfig = {
|
|
10657
|
+
files: ["**/*.{cts,mts,ts,tsx}"],
|
|
10658
|
+
languageOptions: pasikaAppLanguageOptions,
|
|
10659
|
+
plugins: { pasika: pasikaPlugin },
|
|
10660
|
+
rules: { "pasika/file-length": "error" }
|
|
10661
|
+
};
|
|
10180
10662
|
var pasikaNextjsAppConfig = {
|
|
10181
10663
|
files: ["src/**/*.{cjs,cts,js,jsx,mjs,mts,ts,tsx}"],
|
|
10182
10664
|
languageOptions: pasikaAppLanguageOptions,
|
|
@@ -10249,7 +10731,12 @@ var documentationConfig = {
|
|
|
10249
10731
|
language: "markdown/gfm",
|
|
10250
10732
|
rules: Object.fromEntries(documentationRuleIds.map((id) => [id, "error"]))
|
|
10251
10733
|
};
|
|
10252
|
-
var pasikaApp = [
|
|
10734
|
+
var pasikaApp = [
|
|
10735
|
+
pasikaAppPackageJsonConfig,
|
|
10736
|
+
zirkaConfig,
|
|
10737
|
+
documentationConfig,
|
|
10738
|
+
pasikaTypeScriptFileLengthConfig
|
|
10739
|
+
];
|
|
10253
10740
|
var pasikaNextjsAppWithDiagnostic = (preset) => {
|
|
10254
10741
|
let checked = false;
|
|
10255
10742
|
return new Proxy(preset, {
|