pasika 0.10.94 → 0.10.96
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 +1 -0
- package/dist/eslint/pasika/index.js +638 -150
- 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
|
};
|
|
@@ -3970,7 +3985,7 @@ var importBoundariesRule = {
|
|
|
3970
3985
|
const isAppLocalStyleImport = importerLayer === "app" && importedLayer === "app" && styleExtensions.has(extension);
|
|
3971
3986
|
const importedIsRootSupport = rootSupportFolders.has(importedLayer);
|
|
3972
3987
|
const importedIsSameConfig = importerLayer === "config" && importedLayer === "config" && importer[1] === imported[1];
|
|
3973
|
-
const isAllowed = !isCodeModule && importerLayer === "app" && isAppLocalStyleImport || isCodeModule && importerLayer === "app" && (importedLayer === "compositions" || importedLayer === "features" || importedLayer === "shared" || importedIsRootSupport) || isCodeModule && importerLayer === "compositions" && (importedLayer === "compositions" || importedLayer === "features" || importedLayer === "shared" || importedIsRootSupport) || isCodeModule && importerLayer === "features" && (importedLayer === "features" && importerFeature === importedFeature || importedLayer === "shared" || importedIsRootSupport) || isCodeModule && importerLayer === "shared" && (importedLayer === "shared" || importedIsRootSupport) || isCodeModule && rootSupportFolders.has(importerLayer) && importedIsRootSupport && (importerLayer !== "config" || importedLayer !== "config" || importedIsSameConfig);
|
|
3988
|
+
const isAllowed = !isCodeModule && importerLayer === "app" && isAppLocalStyleImport || isCodeModule && importerLayer === "app" && (importedLayer === "compositions" || importedLayer === "features" || importedLayer === "shared" || importedIsRootSupport) || isCodeModule && importerLayer === "compositions" && (importedLayer === "compositions" || importedLayer === "features" || importedLayer === "shared" || importedIsRootSupport) || isCodeModule && importerLayer === "features" && (importedLayer === "features" && importerFeature === importedFeature || importedLayer === "shared" || importedIsRootSupport) || isCodeModule && importerLayer === "shared" && (importedLayer === "shared" || importedIsRootSupport) || isCodeModule && importer.length === 1 && importedIsRootSupport || isCodeModule && rootSupportFolders.has(importerLayer) && importedIsRootSupport && (importerLayer !== "config" || importedLayer !== "config" || importedIsSameConfig);
|
|
3974
3989
|
if (!isAllowed) {
|
|
3975
3990
|
context.report({
|
|
3976
3991
|
node: source,
|
|
@@ -4069,12 +4084,13 @@ var importThroughIndexRule = {
|
|
|
4069
4084
|
schema: [],
|
|
4070
4085
|
type: "problem",
|
|
4071
4086
|
docs: {
|
|
4072
|
-
description: "
|
|
4087
|
+
description: "Enforce public support barrels and direct sibling constants imports."
|
|
4073
4088
|
}
|
|
4074
4089
|
},
|
|
4075
4090
|
create(context) {
|
|
4076
4091
|
const filename = path32.resolve(context.filename);
|
|
4077
4092
|
const sourceRoot = sourceRootOf2(context, filename);
|
|
4093
|
+
const importerSegments = segmentsOf(filename, sourceRoot);
|
|
4078
4094
|
return {
|
|
4079
4095
|
Program(node) {
|
|
4080
4096
|
for (const specifier of importSpecifiers(context.sourceCode.text)) {
|
|
@@ -4085,8 +4101,19 @@ var importThroughIndexRule = {
|
|
|
4085
4101
|
(segment) => ["constants", "types", "schemas"].includes(segment)
|
|
4086
4102
|
);
|
|
4087
4103
|
const supportFolder = supportFolderIndex >= 0 ? targetSegments[supportFolderIndex] : void 0;
|
|
4088
|
-
if (!supportFolder
|
|
4104
|
+
if (!supportFolder) continue;
|
|
4089
4105
|
const folderIndex = targetSegments.slice(0, supportFolderIndex + 1);
|
|
4106
|
+
const withinSameSupportFolder = importerSegments.length > supportFolderIndex + 1 && folderIndex.every((segment, index) => importerSegments[index] === segment);
|
|
4107
|
+
if (path32.basename(target).startsWith("index.")) {
|
|
4108
|
+
if (supportFolder === "constants" && withinSameSupportFolder) {
|
|
4109
|
+
context.report({
|
|
4110
|
+
node,
|
|
4111
|
+
message: `Import sibling constants directly instead of through "${specifier}" to avoid circular barrel imports. See the next-codebase-guide constants rule.`
|
|
4112
|
+
});
|
|
4113
|
+
}
|
|
4114
|
+
continue;
|
|
4115
|
+
}
|
|
4116
|
+
if (withinSameSupportFolder) continue;
|
|
4090
4117
|
const expected = `@/${folderIndex.join("/")}`;
|
|
4091
4118
|
context.report({
|
|
4092
4119
|
node,
|
|
@@ -4602,10 +4629,10 @@ function localePlacement(text) {
|
|
|
4602
4629
|
const sourceFile = ts6.createSourceFile("locales.ts", text, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
|
|
4603
4630
|
for (const statement of sourceFile.statements) {
|
|
4604
4631
|
if (!ts6.isVariableStatement(statement)) continue;
|
|
4605
|
-
const
|
|
4632
|
+
const isExported3 = (ts6.getModifiers(statement) ?? []).some(
|
|
4606
4633
|
(modifier) => modifier.kind === ts6.SyntaxKind.ExportKeyword
|
|
4607
4634
|
);
|
|
4608
|
-
if (!
|
|
4635
|
+
if (!isExported3) continue;
|
|
4609
4636
|
for (const declaration of statement.declarationList.declarations) {
|
|
4610
4637
|
if (!ts6.isIdentifier(declaration.name) || declaration.name.text !== "locales") continue;
|
|
4611
4638
|
if (!declaration.initializer || !ts6.isObjectLiteralExpression(declaration.initializer)) continue;
|
|
@@ -6349,7 +6376,7 @@ var preferEnumRule = {
|
|
|
6349
6376
|
}
|
|
6350
6377
|
for (const unionCall of discriminatedUnions) {
|
|
6351
6378
|
const [discriminatorArg, optionsArg] = unionCall.arguments ?? [];
|
|
6352
|
-
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) {
|
|
6353
6380
|
continue;
|
|
6354
6381
|
}
|
|
6355
6382
|
for (const option of optionsArg.elements) {
|
|
@@ -6379,7 +6406,7 @@ var preferEnumRule = {
|
|
|
6379
6406
|
}
|
|
6380
6407
|
const expression = node.expression;
|
|
6381
6408
|
if (!expression || expression.type !== "ObjectExpression") return;
|
|
6382
|
-
if (expression.properties.length
|
|
6409
|
+
if (expression.properties.length < 2) return;
|
|
6383
6410
|
if (!expression.properties.every(isEnumConvertibleProperty)) return;
|
|
6384
6411
|
context.report({
|
|
6385
6412
|
node,
|
|
@@ -7097,7 +7124,7 @@ var repeatedNumericValueRule = {
|
|
|
7097
7124
|
schema: [],
|
|
7098
7125
|
type: "problem",
|
|
7099
7126
|
docs: {
|
|
7100
|
-
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."
|
|
7101
7128
|
}
|
|
7102
7129
|
},
|
|
7103
7130
|
create(context) {
|
|
@@ -7132,7 +7159,467 @@ var repeatedNumericValueRule = {
|
|
|
7132
7159
|
context.report({
|
|
7133
7160
|
node,
|
|
7134
7161
|
loc: { line: literal.line, column: 0 },
|
|
7135
|
-
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)
|
|
7136
7623
|
});
|
|
7137
7624
|
}
|
|
7138
7625
|
}
|
|
@@ -7322,7 +7809,7 @@ var repeatedStructureRule = {
|
|
|
7322
7809
|
|
|
7323
7810
|
// eslint/rules/require-barrel-star-exports.ts
|
|
7324
7811
|
import fs5 from "fs";
|
|
7325
|
-
import
|
|
7812
|
+
import path50 from "path";
|
|
7326
7813
|
var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
|
|
7327
7814
|
var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
|
|
7328
7815
|
var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
@@ -7330,9 +7817,9 @@ function resolveSiblingModule(indexFile, specifier) {
|
|
|
7330
7817
|
if (!specifier.startsWith("./")) return void 0;
|
|
7331
7818
|
const relative = specifier.slice(2);
|
|
7332
7819
|
if (!relative || relative.includes("/")) return void 0;
|
|
7333
|
-
const directory =
|
|
7334
|
-
const direct =
|
|
7335
|
-
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}`);
|
|
7336
7823
|
return candidates.find((candidate) => fs5.existsSync(candidate) && fs5.statSync(candidate).isFile());
|
|
7337
7824
|
}
|
|
7338
7825
|
var requireBarrelStarExportsRule = {
|
|
@@ -7345,9 +7832,9 @@ var requireBarrelStarExportsRule = {
|
|
|
7345
7832
|
fixable: "code"
|
|
7346
7833
|
},
|
|
7347
7834
|
create(context) {
|
|
7348
|
-
const filename =
|
|
7349
|
-
if (!INDEX_NAMES.has(
|
|
7350
|
-
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 {};
|
|
7351
7838
|
return {
|
|
7352
7839
|
ExportNamedDeclaration(node) {
|
|
7353
7840
|
const sourceNode = node.source;
|
|
@@ -7400,7 +7887,7 @@ var requireBarrelStarExportsRule = {
|
|
|
7400
7887
|
};
|
|
7401
7888
|
|
|
7402
7889
|
// eslint/rules/root-support-placement.ts
|
|
7403
|
-
import
|
|
7890
|
+
import path51 from "path";
|
|
7404
7891
|
function isSupportFolder(value) {
|
|
7405
7892
|
return value === "utils" || value === "types" || value === "schemas" || value === "constants";
|
|
7406
7893
|
}
|
|
@@ -7433,7 +7920,7 @@ var rootSupportPlacementRule = {
|
|
|
7433
7920
|
},
|
|
7434
7921
|
create(context) {
|
|
7435
7922
|
const sourceRoot = sourceRootOf(context);
|
|
7436
|
-
const file =
|
|
7923
|
+
const file = path51.resolve(context.filename);
|
|
7437
7924
|
const segments = segmentsOf(file, sourceRoot);
|
|
7438
7925
|
const folderSegments = folderSegmentsOf(file, sourceRoot);
|
|
7439
7926
|
const supportFolder = folderSegments[folderSegments.length - 1];
|
|
@@ -7479,8 +7966,8 @@ var rootSupportPlacementRule = {
|
|
|
7479
7966
|
};
|
|
7480
7967
|
|
|
7481
7968
|
// eslint/rules/route-handler-shape.ts
|
|
7482
|
-
import
|
|
7483
|
-
import
|
|
7969
|
+
import path52 from "path";
|
|
7970
|
+
import ts12 from "typescript";
|
|
7484
7971
|
var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
7485
7972
|
var REQUIRED_BOUNDARY = "withResponse";
|
|
7486
7973
|
function isFunctionLike(node) {
|
|
@@ -7498,33 +7985,33 @@ function findHandler(node) {
|
|
|
7498
7985
|
return void 0;
|
|
7499
7986
|
}
|
|
7500
7987
|
function isLoop(node) {
|
|
7501
|
-
return
|
|
7988
|
+
return ts12.isForStatement(node) || ts12.isForOfStatement(node) || ts12.isForInStatement(node) || ts12.isWhileStatement(node) || ts12.isDoStatement(node);
|
|
7502
7989
|
}
|
|
7503
7990
|
function isFunctionBoundary(node) {
|
|
7504
|
-
return
|
|
7991
|
+
return ts12.isFunctionExpression(node) || ts12.isArrowFunction(node) || ts12.isFunctionDeclaration(node);
|
|
7505
7992
|
}
|
|
7506
7993
|
function analyzeHandlerBody(body, sourceText) {
|
|
7507
7994
|
const start = body.range?.[0] ?? 0;
|
|
7508
7995
|
const end = body.range?.[1] ?? sourceText.length;
|
|
7509
|
-
const sourceFile =
|
|
7996
|
+
const sourceFile = ts12.createSourceFile(
|
|
7510
7997
|
"route.ts",
|
|
7511
7998
|
sourceText.slice(start, end),
|
|
7512
|
-
|
|
7999
|
+
ts12.ScriptTarget.Latest,
|
|
7513
8000
|
true,
|
|
7514
|
-
|
|
8001
|
+
ts12.ScriptKind.TS
|
|
7515
8002
|
);
|
|
7516
8003
|
const kinds = /* @__PURE__ */ new Set();
|
|
7517
8004
|
const calledNames = /* @__PURE__ */ new Set();
|
|
7518
8005
|
const visit = (node) => {
|
|
7519
|
-
if (
|
|
8006
|
+
if (ts12.isTryStatement(node)) kinds.add("try");
|
|
7520
8007
|
if (isLoop(node)) kinds.add("loop");
|
|
7521
|
-
if (
|
|
7522
|
-
if (
|
|
8008
|
+
if (ts12.isIfStatement(node)) kinds.add("if");
|
|
8009
|
+
if (ts12.isCallExpression(node) && ts12.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
|
|
7523
8010
|
kinds.add("map");
|
|
7524
8011
|
}
|
|
7525
|
-
if (
|
|
8012
|
+
if (ts12.isCallExpression(node) && ts12.isIdentifier(node.expression)) calledNames.add(node.expression.text);
|
|
7526
8013
|
if (isFunctionBoundary(node)) return;
|
|
7527
|
-
|
|
8014
|
+
ts12.forEachChild(node, visit);
|
|
7528
8015
|
};
|
|
7529
8016
|
visit(sourceFile);
|
|
7530
8017
|
return { kinds, calledNames };
|
|
@@ -7564,7 +8051,7 @@ var routeHandlerShapeRule = {
|
|
|
7564
8051
|
}
|
|
7565
8052
|
},
|
|
7566
8053
|
create(context) {
|
|
7567
|
-
if (
|
|
8054
|
+
if (path52.basename(context.filename) !== "route.ts") return {};
|
|
7568
8055
|
const sourceText = context.sourceCode.text;
|
|
7569
8056
|
function reportUnwrapped(node, name) {
|
|
7570
8057
|
context.report({
|
|
@@ -7623,7 +8110,7 @@ var routeHandlerShapeRule = {
|
|
|
7623
8110
|
};
|
|
7624
8111
|
|
|
7625
8112
|
// eslint/rules/schema-casing.ts
|
|
7626
|
-
import
|
|
8113
|
+
import path53 from "path";
|
|
7627
8114
|
function isCamelCase(name) {
|
|
7628
8115
|
return /^[a-z][a-zA-Z0-9]*$/.test(name);
|
|
7629
8116
|
}
|
|
@@ -7651,9 +8138,9 @@ var schemaCasingRule = {
|
|
|
7651
8138
|
}
|
|
7652
8139
|
},
|
|
7653
8140
|
create(context) {
|
|
7654
|
-
const filename =
|
|
8141
|
+
const filename = path53.resolve(context.filename);
|
|
7655
8142
|
const sourceRoot = sourceRootOf(context);
|
|
7656
|
-
if (!filename.startsWith(sourceRoot +
|
|
8143
|
+
if (!filename.startsWith(sourceRoot + path53.sep)) return {};
|
|
7657
8144
|
let zodLocalName;
|
|
7658
8145
|
return {
|
|
7659
8146
|
ImportDeclaration(node) {
|
|
@@ -7685,39 +8172,39 @@ var schemaCasingRule = {
|
|
|
7685
8172
|
};
|
|
7686
8173
|
|
|
7687
8174
|
// eslint/rules/sole-state-owner.ts
|
|
7688
|
-
import
|
|
7689
|
-
import
|
|
8175
|
+
import path54 from "path";
|
|
8176
|
+
import ts13 from "typescript";
|
|
7690
8177
|
function findStateHooks(node) {
|
|
7691
8178
|
const hooks = [];
|
|
7692
8179
|
const visit = (child) => {
|
|
7693
|
-
if (
|
|
7694
|
-
if (
|
|
8180
|
+
if (ts13.isCallExpression(child) && ts13.isIdentifier(child.expression) && child.expression.text === "useState") {
|
|
8181
|
+
if (ts13.isVariableDeclaration(child.parent)) {
|
|
7695
8182
|
const { name } = child.parent;
|
|
7696
|
-
if (
|
|
8183
|
+
if (ts13.isArrayBindingPattern(name) && name.elements.length >= 2) {
|
|
7697
8184
|
const value = name.elements[0];
|
|
7698
8185
|
const updater = name.elements[1];
|
|
7699
|
-
if (value && updater &&
|
|
8186
|
+
if (value && updater && ts13.isBindingElement(value) && ts13.isBindingElement(updater)) {
|
|
7700
8187
|
const valueName = value.name;
|
|
7701
8188
|
const updaterName = updater.name;
|
|
7702
|
-
if (
|
|
8189
|
+
if (ts13.isIdentifier(valueName) && ts13.isIdentifier(updaterName)) {
|
|
7703
8190
|
hooks.push({ value: valueName.text, updater: updaterName.text });
|
|
7704
8191
|
}
|
|
7705
8192
|
}
|
|
7706
8193
|
}
|
|
7707
8194
|
}
|
|
7708
8195
|
}
|
|
7709
|
-
|
|
8196
|
+
ts13.forEachChild(child, visit);
|
|
7710
8197
|
};
|
|
7711
8198
|
visit(node);
|
|
7712
8199
|
return hooks;
|
|
7713
8200
|
}
|
|
7714
8201
|
function isHookUsage(node, hook) {
|
|
7715
|
-
if (
|
|
8202
|
+
if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression) && node.expression.text === hook.updater) {
|
|
7716
8203
|
return "updater";
|
|
7717
8204
|
}
|
|
7718
|
-
if (
|
|
8205
|
+
if (ts13.isIdentifier(node) && node.text === hook.value) {
|
|
7719
8206
|
const parent = node.parent;
|
|
7720
|
-
if (
|
|
8207
|
+
if (ts13.isBindingElement(parent) || ts13.isPropertyAccessExpression(parent) || ts13.isShorthandPropertyAssignment(parent)) {
|
|
7721
8208
|
return void 0;
|
|
7722
8209
|
}
|
|
7723
8210
|
return "value";
|
|
@@ -7727,16 +8214,16 @@ function isHookUsage(node, hook) {
|
|
|
7727
8214
|
function topLevelJsxChildren(initial) {
|
|
7728
8215
|
if (!initial) return void 0;
|
|
7729
8216
|
let expression = initial;
|
|
7730
|
-
while (
|
|
7731
|
-
if (
|
|
8217
|
+
while (ts13.isParenthesizedExpression(expression)) expression = expression.expression;
|
|
8218
|
+
if (ts13.isJsxFragment(expression)) {
|
|
7732
8219
|
const children = expression.children.filter(
|
|
7733
|
-
(c) => !
|
|
8220
|
+
(c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
|
|
7734
8221
|
);
|
|
7735
8222
|
return { root: expression, children };
|
|
7736
8223
|
}
|
|
7737
|
-
if (
|
|
8224
|
+
if (ts13.isJsxElement(expression)) {
|
|
7738
8225
|
const children = expression.children.filter(
|
|
7739
|
-
(c) => !
|
|
8226
|
+
(c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
|
|
7740
8227
|
);
|
|
7741
8228
|
return { root: expression, children };
|
|
7742
8229
|
}
|
|
@@ -7750,8 +8237,8 @@ function collectUsesIn(child, hook) {
|
|
|
7750
8237
|
positions.push(node);
|
|
7751
8238
|
count += 1;
|
|
7752
8239
|
}
|
|
7753
|
-
if (
|
|
7754
|
-
|
|
8240
|
+
if (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node)) return;
|
|
8241
|
+
ts13.forEachChild(node, visit);
|
|
7755
8242
|
};
|
|
7756
8243
|
visit(child);
|
|
7757
8244
|
return { positions, count };
|
|
@@ -7765,7 +8252,7 @@ var soleStateOwnerRule = {
|
|
|
7765
8252
|
}
|
|
7766
8253
|
},
|
|
7767
8254
|
create(context) {
|
|
7768
|
-
const filename =
|
|
8255
|
+
const filename = path54.resolve(context.filename);
|
|
7769
8256
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
7770
8257
|
const text = context.sourceCode.text;
|
|
7771
8258
|
const components = parseComponentInfo(text, filename);
|
|
@@ -7790,18 +8277,18 @@ var soleStateOwnerRule = {
|
|
|
7790
8277
|
}
|
|
7791
8278
|
};
|
|
7792
8279
|
function analyzeSoleOwner(declaration, hook) {
|
|
7793
|
-
const body =
|
|
7794
|
-
if (!body || !
|
|
8280
|
+
const body = ts13.isFunctionDeclaration(declaration) ? declaration.body : void 0;
|
|
8281
|
+
if (!body || !ts13.isBlock(body)) return void 0;
|
|
7795
8282
|
const returns = [];
|
|
7796
8283
|
const visit = (node) => {
|
|
7797
|
-
if (node !== body && (
|
|
7798
|
-
if (
|
|
7799
|
-
|
|
8284
|
+
if (node !== body && (ts13.isFunctionLike(node) || ts13.isClassLike(node))) return;
|
|
8285
|
+
if (ts13.isReturnStatement(node)) returns.push(node);
|
|
8286
|
+
ts13.forEachChild(node, visit);
|
|
7800
8287
|
};
|
|
7801
8288
|
visit(body);
|
|
7802
8289
|
if (returns.length !== 1) return void 0;
|
|
7803
8290
|
const single = returns[0];
|
|
7804
|
-
if (!single?.expression || !
|
|
8291
|
+
if (!single?.expression || !ts13.isExpression(single.expression)) return void 0;
|
|
7805
8292
|
const returnExpression = single.expression;
|
|
7806
8293
|
const root = topLevelJsxChildren(returnExpression);
|
|
7807
8294
|
if (!root || root.children.length === 0) return void 0;
|
|
@@ -7824,11 +8311,11 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
7824
8311
|
let outside = false;
|
|
7825
8312
|
const visit = (node) => {
|
|
7826
8313
|
if (outside) return;
|
|
7827
|
-
if (node !== declaration && (
|
|
8314
|
+
if (node !== declaration && (ts13.isFunctionDeclaration(node) || ts13.isClassDeclaration(node))) return;
|
|
7828
8315
|
if (isHookUsage(node, hook)) {
|
|
7829
8316
|
let current = node;
|
|
7830
8317
|
let isInJsxChild = false;
|
|
7831
|
-
while (!
|
|
8318
|
+
while (!ts13.isSourceFile(current)) {
|
|
7832
8319
|
if (children.includes(current)) {
|
|
7833
8320
|
isInJsxChild = true;
|
|
7834
8321
|
break;
|
|
@@ -7837,14 +8324,14 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
7837
8324
|
}
|
|
7838
8325
|
if (!isInJsxChild) outside = true;
|
|
7839
8326
|
}
|
|
7840
|
-
|
|
8327
|
+
ts13.forEachChild(node, visit);
|
|
7841
8328
|
};
|
|
7842
8329
|
visit(declaration);
|
|
7843
8330
|
return outside;
|
|
7844
8331
|
}
|
|
7845
8332
|
|
|
7846
8333
|
// eslint/rules/source-under-src.ts
|
|
7847
|
-
import
|
|
8334
|
+
import path55 from "path";
|
|
7848
8335
|
var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
|
|
7849
8336
|
".agents",
|
|
7850
8337
|
".cache",
|
|
@@ -7885,14 +8372,14 @@ var sourceUnderSrcRule = {
|
|
|
7885
8372
|
}
|
|
7886
8373
|
},
|
|
7887
8374
|
create(context) {
|
|
7888
|
-
const filename =
|
|
8375
|
+
const filename = path55.resolve(context.filename);
|
|
7889
8376
|
if (!MODULE_EXTENSION.test(filename)) return {};
|
|
7890
|
-
const relative =
|
|
8377
|
+
const relative = path55.relative(context.cwd, filename).replace(/\\/g, "/");
|
|
7891
8378
|
if (relative === "src" || relative.startsWith("src/")) return {};
|
|
7892
8379
|
const topLevel = relative.split("/")[0] ?? "";
|
|
7893
8380
|
if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
|
|
7894
8381
|
if (!relative.includes("/")) {
|
|
7895
|
-
const basename =
|
|
8382
|
+
const basename = path55.basename(filename);
|
|
7896
8383
|
if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
|
|
7897
8384
|
}
|
|
7898
8385
|
return {
|
|
@@ -7908,7 +8395,7 @@ var sourceUnderSrcRule = {
|
|
|
7908
8395
|
};
|
|
7909
8396
|
|
|
7910
8397
|
// eslint/rules/stay-flat.ts
|
|
7911
|
-
import
|
|
8398
|
+
import path56 from "path";
|
|
7912
8399
|
var stayFlatRule = {
|
|
7913
8400
|
meta: {
|
|
7914
8401
|
schema: [],
|
|
@@ -7919,7 +8406,7 @@ var stayFlatRule = {
|
|
|
7919
8406
|
},
|
|
7920
8407
|
create(context) {
|
|
7921
8408
|
const sourceRoot = sourceRootOf(context);
|
|
7922
|
-
const file =
|
|
8409
|
+
const file = path56.resolve(context.filename);
|
|
7923
8410
|
const segments = segmentsOf(file, sourceRoot);
|
|
7924
8411
|
if (segments.length !== 3 || segments[0] !== "features") return {};
|
|
7925
8412
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -7959,7 +8446,7 @@ var stayFlatRule = {
|
|
|
7959
8446
|
};
|
|
7960
8447
|
|
|
7961
8448
|
// eslint/rules/support-file-placement.ts
|
|
7962
|
-
import
|
|
8449
|
+
import path57 from "path";
|
|
7963
8450
|
var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
|
|
7964
8451
|
var EXPORT_KIND_BY_SUPPORT_FOLDER = /* @__PURE__ */ new Map([
|
|
7965
8452
|
["constants", "constant"],
|
|
@@ -7984,7 +8471,7 @@ var supportFilePlacementRule = {
|
|
|
7984
8471
|
},
|
|
7985
8472
|
create(context) {
|
|
7986
8473
|
const sourceRoot = sourceRootOf(context);
|
|
7987
|
-
const supportFile =
|
|
8474
|
+
const supportFile = path57.resolve(context.filename);
|
|
7988
8475
|
const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
|
|
7989
8476
|
const supportFolder = currentFolder[currentFolder.length - 1];
|
|
7990
8477
|
if (supportFolder === void 0 || !SUPPORT_FOLDERS.has(supportFolder)) return {};
|
|
@@ -8038,7 +8525,7 @@ var supportFilePlacementRule = {
|
|
|
8038
8525
|
|
|
8039
8526
|
// eslint/rules/support-folder-shape.ts
|
|
8040
8527
|
import fs6 from "fs";
|
|
8041
|
-
import
|
|
8528
|
+
import path58 from "path";
|
|
8042
8529
|
var SUPPORT_FOLDERS4 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
|
|
8043
8530
|
var INDEX_NAMES2 = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
|
|
8044
8531
|
var supportFolderShapeRule = {
|
|
@@ -8050,12 +8537,12 @@ var supportFolderShapeRule = {
|
|
|
8050
8537
|
}
|
|
8051
8538
|
},
|
|
8052
8539
|
create(context) {
|
|
8053
|
-
const filename =
|
|
8054
|
-
const baseName =
|
|
8540
|
+
const filename = path58.resolve(context.filename);
|
|
8541
|
+
const baseName = path58.basename(filename);
|
|
8055
8542
|
if (!INDEX_NAMES2.has(baseName)) return {};
|
|
8056
|
-
const folder =
|
|
8543
|
+
const folder = path58.basename(path58.dirname(filename));
|
|
8057
8544
|
if (!SUPPORT_FOLDERS4.has(folder)) return {};
|
|
8058
|
-
const directory =
|
|
8545
|
+
const directory = path58.dirname(filename);
|
|
8059
8546
|
let entries;
|
|
8060
8547
|
try {
|
|
8061
8548
|
entries = fs6.readdirSync(directory);
|
|
@@ -8073,7 +8560,7 @@ var supportFolderShapeRule = {
|
|
|
8073
8560
|
for (const match of source.matchAll(exportPattern)) {
|
|
8074
8561
|
hasAnyReExport = true;
|
|
8075
8562
|
const specifier = match.groups?.specifier;
|
|
8076
|
-
if (specifier?.startsWith(".")) exportedFiles.add(
|
|
8563
|
+
if (specifier?.startsWith(".")) exportedFiles.add(path58.basename(specifier));
|
|
8077
8564
|
}
|
|
8078
8565
|
const guide = `docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`;
|
|
8079
8566
|
if (siblingModules.length === 0) {
|
|
@@ -8252,11 +8739,11 @@ var baseLayerPairRule = {
|
|
|
8252
8739
|
|
|
8253
8740
|
// eslint/rules/tailwind/css-entry-point.ts
|
|
8254
8741
|
import { statSync as statSync4 } from "fs";
|
|
8255
|
-
import
|
|
8742
|
+
import path61 from "path";
|
|
8256
8743
|
|
|
8257
8744
|
// eslint/rules/tailwind/source-files.ts
|
|
8258
|
-
import { readdirSync as readdirSync3, readFileSync as
|
|
8259
|
-
import
|
|
8745
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
|
|
8746
|
+
import path59 from "path";
|
|
8260
8747
|
var CSS_EXTENSIONS = [".css"];
|
|
8261
8748
|
var MODULE_EXTENSIONS4 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
8262
8749
|
var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS4, ...CSS_EXTENSIONS];
|
|
@@ -8269,7 +8756,7 @@ function findFiles(dir, extensions) {
|
|
|
8269
8756
|
}
|
|
8270
8757
|
return entries.flatMap((entry) => {
|
|
8271
8758
|
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
8272
|
-
const entryPath =
|
|
8759
|
+
const entryPath = path59.join(dir, entry);
|
|
8273
8760
|
let stats;
|
|
8274
8761
|
try {
|
|
8275
8762
|
stats = statSync3(entryPath);
|
|
@@ -8277,7 +8764,7 @@ function findFiles(dir, extensions) {
|
|
|
8277
8764
|
return [];
|
|
8278
8765
|
}
|
|
8279
8766
|
if (stats.isDirectory()) return findFiles(entryPath, extensions);
|
|
8280
|
-
return extensions.includes(
|
|
8767
|
+
return extensions.includes(path59.extname(entry)) ? [entryPath] : [];
|
|
8281
8768
|
});
|
|
8282
8769
|
}
|
|
8283
8770
|
function cachedTextReader() {
|
|
@@ -8286,7 +8773,7 @@ function cachedTextReader() {
|
|
|
8286
8773
|
let text = texts.get(file);
|
|
8287
8774
|
if (text === void 0) {
|
|
8288
8775
|
try {
|
|
8289
|
-
text =
|
|
8776
|
+
text = readFileSync11(file, "utf8");
|
|
8290
8777
|
} catch {
|
|
8291
8778
|
text = "";
|
|
8292
8779
|
}
|
|
@@ -8300,7 +8787,7 @@ function escapeRegExp(text) {
|
|
|
8300
8787
|
}
|
|
8301
8788
|
|
|
8302
8789
|
// eslint/rules/tailwind/stylesheet-graph.ts
|
|
8303
|
-
import
|
|
8790
|
+
import path60 from "path";
|
|
8304
8791
|
function registersTailwind(text) {
|
|
8305
8792
|
return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
|
|
8306
8793
|
}
|
|
@@ -8314,25 +8801,25 @@ function moduleImports(text, fileName) {
|
|
|
8314
8801
|
return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
|
|
8315
8802
|
}
|
|
8316
8803
|
function resolveSpecifier2(fromFile, spec, sourceRoot) {
|
|
8317
|
-
if (spec.startsWith("/")) return
|
|
8318
|
-
if (spec.startsWith("./") || spec.startsWith("../")) return
|
|
8319
|
-
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));
|
|
8320
8807
|
return void 0;
|
|
8321
8808
|
}
|
|
8322
8809
|
function buildStylesheetGraph(options) {
|
|
8323
8810
|
const { cssFiles, sourceRoot, textOf } = options;
|
|
8324
|
-
const cssSet = new Set(cssFiles.map((file) =>
|
|
8811
|
+
const cssSet = new Set(cssFiles.map((file) => path60.normalize(file)));
|
|
8325
8812
|
const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
|
|
8326
8813
|
const reachable = /* @__PURE__ */ new Set();
|
|
8327
8814
|
const queue = [...globals];
|
|
8328
|
-
for (const global of globals) reachable.add(
|
|
8815
|
+
for (const global of globals) reachable.add(path60.normalize(global));
|
|
8329
8816
|
while (queue.length > 0) {
|
|
8330
8817
|
const from = queue.shift();
|
|
8331
8818
|
if (!from) continue;
|
|
8332
8819
|
for (const spec of importedSpecifiers(textOf(from))) {
|
|
8333
8820
|
const target = resolveSpecifier2(from, spec, sourceRoot);
|
|
8334
8821
|
if (!target) continue;
|
|
8335
|
-
const normalized =
|
|
8822
|
+
const normalized = path60.normalize(target);
|
|
8336
8823
|
if (cssSet.has(normalized) && !reachable.has(normalized)) {
|
|
8337
8824
|
reachable.add(normalized);
|
|
8338
8825
|
queue.push(normalized);
|
|
@@ -8344,7 +8831,7 @@ function buildStylesheetGraph(options) {
|
|
|
8344
8831
|
for (const spec of importedSpecifiers(textOf(global))) {
|
|
8345
8832
|
const target = resolveSpecifier2(global, spec, sourceRoot);
|
|
8346
8833
|
if (!target) continue;
|
|
8347
|
-
const normalized =
|
|
8834
|
+
const normalized = path60.normalize(target);
|
|
8348
8835
|
if (cssSet.has(normalized)) directChildren.add(normalized);
|
|
8349
8836
|
}
|
|
8350
8837
|
}
|
|
@@ -8352,8 +8839,8 @@ function buildStylesheetGraph(options) {
|
|
|
8352
8839
|
}
|
|
8353
8840
|
|
|
8354
8841
|
// eslint/rules/tailwind/css-entry-point.ts
|
|
8355
|
-
var APP_STYLES_DIR =
|
|
8356
|
-
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");
|
|
8357
8844
|
var cssEntryPointRule = {
|
|
8358
8845
|
meta: {
|
|
8359
8846
|
schema: [],
|
|
@@ -8379,8 +8866,8 @@ var cssEntryPointRule = {
|
|
|
8379
8866
|
return {
|
|
8380
8867
|
"StyleSheet:exit"(node) {
|
|
8381
8868
|
if (globals.length === 0) return;
|
|
8382
|
-
const current =
|
|
8383
|
-
const relative =
|
|
8869
|
+
const current = path61.normalize(path61.resolve(context.filename));
|
|
8870
|
+
const relative = path61.relative(sourceRoot, current);
|
|
8384
8871
|
if (globals.includes(current)) {
|
|
8385
8872
|
if (globals.length > 1) {
|
|
8386
8873
|
context.report({
|
|
@@ -8396,7 +8883,7 @@ var cssEntryPointRule = {
|
|
|
8396
8883
|
});
|
|
8397
8884
|
return;
|
|
8398
8885
|
}
|
|
8399
|
-
const basename =
|
|
8886
|
+
const basename = path61.basename(current);
|
|
8400
8887
|
const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
|
|
8401
8888
|
if (importCount !== 1) {
|
|
8402
8889
|
context.report({
|
|
@@ -8406,7 +8893,7 @@ var cssEntryPointRule = {
|
|
|
8406
8893
|
}
|
|
8407
8894
|
return;
|
|
8408
8895
|
}
|
|
8409
|
-
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}`);
|
|
8410
8897
|
if (!isInAppStyles) {
|
|
8411
8898
|
context.report({
|
|
8412
8899
|
node,
|
|
@@ -8895,7 +9382,7 @@ var tailwindRules = {
|
|
|
8895
9382
|
};
|
|
8896
9383
|
|
|
8897
9384
|
// eslint/rules/type-extraction.ts
|
|
8898
|
-
import
|
|
9385
|
+
import path62 from "path";
|
|
8899
9386
|
var typeExtractionRule = {
|
|
8900
9387
|
meta: {
|
|
8901
9388
|
schema: [],
|
|
@@ -8906,7 +9393,7 @@ var typeExtractionRule = {
|
|
|
8906
9393
|
},
|
|
8907
9394
|
create(context) {
|
|
8908
9395
|
const sourceRoot = sourceRootOf(context);
|
|
8909
|
-
const file =
|
|
9396
|
+
const file = path62.resolve(context.filename);
|
|
8910
9397
|
const segments = segmentsOf(file, sourceRoot);
|
|
8911
9398
|
if (segments.length === 0) return {};
|
|
8912
9399
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -9045,9 +9532,9 @@ var uiStateRule = {
|
|
|
9045
9532
|
};
|
|
9046
9533
|
|
|
9047
9534
|
// eslint/rules/unknown-utility.ts
|
|
9048
|
-
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";
|
|
9049
9536
|
import { createRequire } from "module";
|
|
9050
|
-
import
|
|
9537
|
+
import path63 from "path";
|
|
9051
9538
|
var PREFIX_NAMESPACES = {
|
|
9052
9539
|
bg: ["color"],
|
|
9053
9540
|
text: ["color", "text"],
|
|
@@ -9287,7 +9774,7 @@ function stylesheetFiles(dir) {
|
|
|
9287
9774
|
}
|
|
9288
9775
|
return entries.flatMap((entry) => {
|
|
9289
9776
|
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
9290
|
-
const entryPath =
|
|
9777
|
+
const entryPath = path63.join(dir, entry);
|
|
9291
9778
|
let stats;
|
|
9292
9779
|
try {
|
|
9293
9780
|
stats = statSync6(entryPath);
|
|
@@ -9295,7 +9782,7 @@ function stylesheetFiles(dir) {
|
|
|
9295
9782
|
return [];
|
|
9296
9783
|
}
|
|
9297
9784
|
if (stats.isDirectory()) return stylesheetFiles(entryPath);
|
|
9298
|
-
return
|
|
9785
|
+
return path63.extname(entry) === ".css" ? [entryPath] : [];
|
|
9299
9786
|
});
|
|
9300
9787
|
}
|
|
9301
9788
|
function packageNameOf(specifier) {
|
|
@@ -9306,24 +9793,24 @@ function packageNameOf(specifier) {
|
|
|
9306
9793
|
function resolvePackageStylesheet(fromFile, specifier) {
|
|
9307
9794
|
const packageName = packageNameOf(specifier);
|
|
9308
9795
|
if (!packageName || packageName === "tailwindcss") return void 0;
|
|
9309
|
-
let directory =
|
|
9310
|
-
while (directory !==
|
|
9311
|
-
const packageRoot =
|
|
9312
|
-
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");
|
|
9313
9800
|
if (existsSync6(manifestPath)) {
|
|
9314
9801
|
try {
|
|
9315
|
-
const manifest =
|
|
9802
|
+
const manifest = readFileSync12(manifestPath, "utf8");
|
|
9316
9803
|
const stylesheet = /"style"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
|
|
9317
9804
|
const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
|
|
9318
9805
|
const target = stylesheet ?? main;
|
|
9319
9806
|
if (!target) return void 0;
|
|
9320
|
-
const resolved =
|
|
9807
|
+
const resolved = path63.resolve(packageRoot, target);
|
|
9321
9808
|
return existsSync6(resolved) ? resolved : void 0;
|
|
9322
9809
|
} catch {
|
|
9323
9810
|
return void 0;
|
|
9324
9811
|
}
|
|
9325
9812
|
}
|
|
9326
|
-
directory =
|
|
9813
|
+
directory = path63.dirname(directory);
|
|
9327
9814
|
}
|
|
9328
9815
|
return void 0;
|
|
9329
9816
|
}
|
|
@@ -9332,7 +9819,7 @@ function inventoryStylesheetFiles(projectFiles) {
|
|
|
9332
9819
|
for (const file of projectFiles) {
|
|
9333
9820
|
let css2;
|
|
9334
9821
|
try {
|
|
9335
|
-
css2 =
|
|
9822
|
+
css2 = readFileSync12(file, "utf8");
|
|
9336
9823
|
} catch {
|
|
9337
9824
|
continue;
|
|
9338
9825
|
}
|
|
@@ -9398,7 +9885,7 @@ function readInventory(files) {
|
|
|
9398
9885
|
for (const file of files) {
|
|
9399
9886
|
let css2;
|
|
9400
9887
|
try {
|
|
9401
|
-
css2 =
|
|
9888
|
+
css2 = readFileSync12(file, "utf8");
|
|
9402
9889
|
} catch {
|
|
9403
9890
|
continue;
|
|
9404
9891
|
}
|
|
@@ -9574,7 +10061,7 @@ var unknownUtilityRule = {
|
|
|
9574
10061
|
};
|
|
9575
10062
|
|
|
9576
10063
|
// eslint/rules/util-file-name.ts
|
|
9577
|
-
import
|
|
10064
|
+
import path64 from "path";
|
|
9578
10065
|
function toKebabCase2(value) {
|
|
9579
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();
|
|
9580
10067
|
}
|
|
@@ -9587,7 +10074,7 @@ var utilFileNameRule = {
|
|
|
9587
10074
|
}
|
|
9588
10075
|
},
|
|
9589
10076
|
create(context) {
|
|
9590
|
-
const filename =
|
|
10077
|
+
const filename = path64.resolve(context.filename);
|
|
9591
10078
|
const segments = filename.replace(/\\/g, "/").split("/");
|
|
9592
10079
|
if (!segments.includes("utils")) return {};
|
|
9593
10080
|
let module;
|
|
@@ -9601,13 +10088,13 @@ var utilFileNameRule = {
|
|
|
9601
10088
|
const functionName = functions[0]?.name;
|
|
9602
10089
|
if (!functionName) return {};
|
|
9603
10090
|
const expected = toKebabCase2(functionName);
|
|
9604
|
-
const actual =
|
|
10091
|
+
const actual = path64.basename(filename, path64.extname(filename));
|
|
9605
10092
|
if (!expected || actual === expected) return {};
|
|
9606
10093
|
return {
|
|
9607
10094
|
Program(node) {
|
|
9608
10095
|
context.report({
|
|
9609
10096
|
node,
|
|
9610
|
-
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)}.`
|
|
9611
10098
|
});
|
|
9612
10099
|
}
|
|
9613
10100
|
};
|
|
@@ -9615,7 +10102,7 @@ var utilFileNameRule = {
|
|
|
9615
10102
|
};
|
|
9616
10103
|
|
|
9617
10104
|
// eslint/rules/value-extraction.ts
|
|
9618
|
-
import
|
|
10105
|
+
import path65 from "path";
|
|
9619
10106
|
var valueExtractionRule = {
|
|
9620
10107
|
meta: {
|
|
9621
10108
|
schema: [],
|
|
@@ -9626,7 +10113,7 @@ var valueExtractionRule = {
|
|
|
9626
10113
|
},
|
|
9627
10114
|
create(context) {
|
|
9628
10115
|
const sourceRoot = sourceRootOf(context);
|
|
9629
|
-
const file =
|
|
10116
|
+
const file = path65.resolve(context.filename);
|
|
9630
10117
|
const segments = segmentsOf(file, sourceRoot);
|
|
9631
10118
|
if (segments.length === 0 || segments[0] !== "app") return {};
|
|
9632
10119
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -9647,8 +10134,8 @@ var valueExtractionRule = {
|
|
|
9647
10134
|
};
|
|
9648
10135
|
|
|
9649
10136
|
// eslint/rules/vulyk/tracked-docs.ts
|
|
9650
|
-
import { existsSync as existsSync7, readFileSync as
|
|
9651
|
-
import
|
|
10137
|
+
import { existsSync as existsSync7, readFileSync as readFileSync13 } from "fs";
|
|
10138
|
+
import path66 from "path";
|
|
9652
10139
|
var PASIKA_REPO = "Bredansky/pasika";
|
|
9653
10140
|
var BASE_REQUIRED_TRACKED_DOCS = [
|
|
9654
10141
|
{ name: "documentation-guide", path: "docs/documentation-guide" },
|
|
@@ -9659,13 +10146,13 @@ var NEXTJS_REQUIRED_TRACKED_DOCS = [
|
|
|
9659
10146
|
{ name: "next-codebase-guide", path: "docs/next-codebase-guide" },
|
|
9660
10147
|
{ name: "next-tailwind-guide", path: "docs/next-tailwind-guide" }
|
|
9661
10148
|
];
|
|
9662
|
-
function
|
|
10149
|
+
function memberName7(member) {
|
|
9663
10150
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
9664
10151
|
}
|
|
9665
10152
|
function hasDependency(root, name) {
|
|
9666
|
-
const section = root.members.find((member) =>
|
|
10153
|
+
const section = root.members.find((member) => memberName7(member) === "dependencies");
|
|
9667
10154
|
if (section?.value.type !== "Object") return false;
|
|
9668
|
-
return section.value.members.some((member) =>
|
|
10155
|
+
return section.value.members.some((member) => memberName7(member) === name);
|
|
9669
10156
|
}
|
|
9670
10157
|
var trackedDocsRule = {
|
|
9671
10158
|
meta: {
|
|
@@ -9681,8 +10168,8 @@ var trackedDocsRule = {
|
|
|
9681
10168
|
if (!context.filename.endsWith("package.json")) return;
|
|
9682
10169
|
const root = node.body;
|
|
9683
10170
|
if (root.type !== "Object") return;
|
|
9684
|
-
const projectRoot =
|
|
9685
|
-
const configPath =
|
|
10171
|
+
const projectRoot = path66.dirname(path66.resolve(context.filename));
|
|
10172
|
+
const configPath = path66.join(projectRoot, "vulyk.config.ts");
|
|
9686
10173
|
if (!existsSync7(configPath)) {
|
|
9687
10174
|
context.report({
|
|
9688
10175
|
node,
|
|
@@ -9690,7 +10177,7 @@ var trackedDocsRule = {
|
|
|
9690
10177
|
});
|
|
9691
10178
|
return;
|
|
9692
10179
|
}
|
|
9693
|
-
const config =
|
|
10180
|
+
const config = readFileSync13(configPath, "utf8");
|
|
9694
10181
|
if (!config.includes(PASIKA_REPO)) {
|
|
9695
10182
|
context.report({
|
|
9696
10183
|
node,
|
|
@@ -9707,7 +10194,7 @@ var trackedDocsRule = {
|
|
|
9707
10194
|
});
|
|
9708
10195
|
}
|
|
9709
10196
|
}
|
|
9710
|
-
const agentsPath =
|
|
10197
|
+
const agentsPath = path66.join(projectRoot, "AGENTS.md");
|
|
9711
10198
|
if (!existsSync7(agentsPath)) {
|
|
9712
10199
|
context.report({
|
|
9713
10200
|
node,
|
|
@@ -9720,14 +10207,14 @@ var trackedDocsRule = {
|
|
|
9720
10207
|
};
|
|
9721
10208
|
|
|
9722
10209
|
// eslint/rules/vulyk/vulyk-dependency.ts
|
|
9723
|
-
function
|
|
10210
|
+
function memberName8(member) {
|
|
9724
10211
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
9725
10212
|
}
|
|
9726
10213
|
function dependency(root, sectionName) {
|
|
9727
10214
|
if (root.type !== "Object") return void 0;
|
|
9728
|
-
const section = root.members.find((member) =>
|
|
10215
|
+
const section = root.members.find((member) => memberName8(member) === sectionName);
|
|
9729
10216
|
if (section?.value.type !== "Object") return void 0;
|
|
9730
|
-
return section.value.members.find((member) =>
|
|
10217
|
+
return section.value.members.find((member) => memberName8(member) === "vulyk");
|
|
9731
10218
|
}
|
|
9732
10219
|
var vulykDependencyRule = {
|
|
9733
10220
|
meta: {
|
|
@@ -9768,9 +10255,9 @@ var vulykRules = {
|
|
|
9768
10255
|
// eslint/rules/with-response-helper.ts
|
|
9769
10256
|
var HELPER3 = "withResponse";
|
|
9770
10257
|
var ENTRY3 = "pasika/with-response";
|
|
9771
|
-
var
|
|
9772
|
-
var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${
|
|
9773
|
-
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}`;
|
|
9774
10261
|
function isNamed3(node, name) {
|
|
9775
10262
|
return node?.type === "Identifier" && node.name === name;
|
|
9776
10263
|
}
|
|
@@ -9807,7 +10294,7 @@ var withResponseHelperRule = {
|
|
|
9807
10294
|
|
|
9808
10295
|
// eslint/rules/zirka-baseline.ts
|
|
9809
10296
|
import fs7 from "fs";
|
|
9810
|
-
import
|
|
10297
|
+
import path67 from "path";
|
|
9811
10298
|
var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
|
|
9812
10299
|
var PRETTIER_CONFIGS = [
|
|
9813
10300
|
"prettier.config.mjs",
|
|
@@ -9826,10 +10313,10 @@ var zirkaBaselineRule = {
|
|
|
9826
10313
|
}
|
|
9827
10314
|
},
|
|
9828
10315
|
create(context) {
|
|
9829
|
-
const filename =
|
|
9830
|
-
const basename =
|
|
10316
|
+
const filename = path67.resolve(context.filename);
|
|
10317
|
+
const basename = path67.basename(filename);
|
|
9831
10318
|
if (!ESLINT_CONFIG.test(basename)) return {};
|
|
9832
|
-
const projectRoot =
|
|
10319
|
+
const projectRoot = path67.dirname(filename);
|
|
9833
10320
|
const report3 = (message) => {
|
|
9834
10321
|
context.report({
|
|
9835
10322
|
node: context.sourceCode.ast,
|
|
@@ -9844,7 +10331,7 @@ var zirkaBaselineRule = {
|
|
|
9844
10331
|
'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
|
|
9845
10332
|
);
|
|
9846
10333
|
}
|
|
9847
|
-
const tsconfigPath =
|
|
10334
|
+
const tsconfigPath = path67.join(projectRoot, "tsconfig.json");
|
|
9848
10335
|
if (!fs7.existsSync(tsconfigPath)) {
|
|
9849
10336
|
report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
|
|
9850
10337
|
} else {
|
|
@@ -9862,13 +10349,13 @@ var zirkaBaselineRule = {
|
|
|
9862
10349
|
report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
|
|
9863
10350
|
}
|
|
9864
10351
|
}
|
|
9865
|
-
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(
|
|
10352
|
+
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path67.join(projectRoot, name)));
|
|
9866
10353
|
if (!prettierConfigFile) {
|
|
9867
10354
|
report3(
|
|
9868
10355
|
"No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
|
|
9869
10356
|
);
|
|
9870
10357
|
} else {
|
|
9871
|
-
const content = fs7.readFileSync(
|
|
10358
|
+
const content = fs7.readFileSync(path67.join(projectRoot, prettierConfigFile), "utf8");
|
|
9872
10359
|
if (!content.includes("zirka")) {
|
|
9873
10360
|
report3(
|
|
9874
10361
|
"The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
|
|
@@ -9891,10 +10378,10 @@ function referencesZirka(sourceCode) {
|
|
|
9891
10378
|
// eslint/rules/zod-fetch-helper.ts
|
|
9892
10379
|
var HELPER4 = "zodFetch";
|
|
9893
10380
|
var ENTRY4 = "pasika/zod-fetch";
|
|
9894
|
-
var
|
|
9895
|
-
var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${
|
|
9896
|
-
var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${
|
|
9897
|
-
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}`;
|
|
9898
10385
|
var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "window", "self", "global"]);
|
|
9899
10386
|
var TEST_FILE2 = /(?:^|[\\/])(?:__tests__|tests)[\\/]|[.](?:test|spec)[.][cm]?[jt]sx?$/;
|
|
9900
10387
|
function isNamed4(node, name) {
|
|
@@ -10014,14 +10501,14 @@ var zodSchemaValidationRule = {
|
|
|
10014
10501
|
};
|
|
10015
10502
|
|
|
10016
10503
|
// eslint/ts-alignment.ts
|
|
10017
|
-
import { readFileSync as
|
|
10504
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
10018
10505
|
import { createRequire as createRequire2 } from "module";
|
|
10019
10506
|
import { join } from "path";
|
|
10020
10507
|
var ownRequire = createRequire2(import.meta.url);
|
|
10021
10508
|
var majorOf = (version) => Number(version.split(".")[0]);
|
|
10022
10509
|
function versionOf(packagePath) {
|
|
10023
10510
|
try {
|
|
10024
|
-
const parsed = JSON.parse(
|
|
10511
|
+
const parsed = JSON.parse(readFileSync14(packagePath, "utf8"));
|
|
10025
10512
|
if (typeof parsed !== "object" || parsed === null || !("version" in parsed)) return null;
|
|
10026
10513
|
return typeof parsed.version === "string" ? parsed.version : null;
|
|
10027
10514
|
} catch {
|
|
@@ -10081,6 +10568,7 @@ var pasikaNextjsAppRules = {
|
|
|
10081
10568
|
"value-extraction": valueExtractionRule,
|
|
10082
10569
|
"constant-casing": constantCasingRule,
|
|
10083
10570
|
"prefer-enum": preferEnumRule,
|
|
10571
|
+
"repeated-semantic-literal": repeatedSemanticLiteralRule,
|
|
10084
10572
|
"prefer-object-destructuring": preferObjectDestructuringRule,
|
|
10085
10573
|
"enum-placement": enumPlacementRule,
|
|
10086
10574
|
"type-extraction": typeExtractionRule,
|