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.
@@ -444,8 +444,8 @@ function parseModule(file) {
444
444
  }
445
445
  continue;
446
446
  }
447
- const isExported2 = ts.canHaveModifiers(statement) ? (ts.getModifiers(statement) ?? []).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) : false;
448
- if (!isExported2) continue;
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: "Require TypeScript enum declarations to live in constants/ folders."
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
- if (path25.basename(path25.dirname(filename)) === "constants") return {};
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: "A TypeScript enum must live in a constants/ folder because it creates runtime values as well as a type. See docs/next-codebase-guide/rules/constants-rule.md"
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: "Require imports of support files to use their support-folder index."
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 || path32.basename(target).startsWith("index.")) continue;
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 isExported2 = (ts6.getModifiers(statement) ?? []).some(
4632
+ const isExported3 = (ts6.getModifiers(statement) ?? []).some(
4606
4633
  (modifier) => modifier.kind === ts6.SyntaxKind.ExportKeyword
4607
4634
  );
4608
- if (!isExported2) continue;
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 === 0) return;
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 extracted constant or enum."
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 or enum at their CCF and import it instead. See docs/next-codebase-guide/rules/constants-rule.md`
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 path47 from "path";
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 = path47.dirname(indexFile);
7334
- const direct = path47.resolve(directory, relative);
7335
- const candidates = path47.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
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 = path47.resolve(context.filename);
7349
- if (!INDEX_NAMES.has(path47.basename(filename))) return {};
7350
- if (!SUPPORT_FOLDERS3.has(path47.basename(path47.dirname(filename)))) return {};
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 path48 from "path";
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 = path48.resolve(context.filename);
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 path49 from "path";
7483
- import ts10 from "typescript";
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 ts10.isForStatement(node) || ts10.isForOfStatement(node) || ts10.isForInStatement(node) || ts10.isWhileStatement(node) || ts10.isDoStatement(node);
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 ts10.isFunctionExpression(node) || ts10.isArrowFunction(node) || ts10.isFunctionDeclaration(node);
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 = ts10.createSourceFile(
7996
+ const sourceFile = ts12.createSourceFile(
7510
7997
  "route.ts",
7511
7998
  sourceText.slice(start, end),
7512
- ts10.ScriptTarget.Latest,
7999
+ ts12.ScriptTarget.Latest,
7513
8000
  true,
7514
- ts10.ScriptKind.TS
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 (ts10.isTryStatement(node)) kinds.add("try");
8006
+ if (ts12.isTryStatement(node)) kinds.add("try");
7520
8007
  if (isLoop(node)) kinds.add("loop");
7521
- if (ts10.isIfStatement(node)) kinds.add("if");
7522
- if (ts10.isCallExpression(node) && ts10.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") {
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 (ts10.isCallExpression(node) && ts10.isIdentifier(node.expression)) calledNames.add(node.expression.text);
8012
+ if (ts12.isCallExpression(node) && ts12.isIdentifier(node.expression)) calledNames.add(node.expression.text);
7526
8013
  if (isFunctionBoundary(node)) return;
7527
- ts10.forEachChild(node, visit);
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 (path49.basename(context.filename) !== "route.ts") return {};
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 path50 from "path";
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 = path50.resolve(context.filename);
8141
+ const filename = path53.resolve(context.filename);
7655
8142
  const sourceRoot = sourceRootOf(context);
7656
- if (!filename.startsWith(sourceRoot + path50.sep)) return {};
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 path51 from "path";
7689
- import ts11 from "typescript";
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 (ts11.isCallExpression(child) && ts11.isIdentifier(child.expression) && child.expression.text === "useState") {
7694
- if (ts11.isVariableDeclaration(child.parent)) {
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 (ts11.isArrayBindingPattern(name) && name.elements.length >= 2) {
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 && ts11.isBindingElement(value) && ts11.isBindingElement(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 (ts11.isIdentifier(valueName) && ts11.isIdentifier(updaterName)) {
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
- ts11.forEachChild(child, visit);
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 (ts11.isCallExpression(node) && ts11.isIdentifier(node.expression) && node.expression.text === hook.updater) {
8202
+ if (ts13.isCallExpression(node) && ts13.isIdentifier(node.expression) && node.expression.text === hook.updater) {
7716
8203
  return "updater";
7717
8204
  }
7718
- if (ts11.isIdentifier(node) && node.text === hook.value) {
8205
+ if (ts13.isIdentifier(node) && node.text === hook.value) {
7719
8206
  const parent = node.parent;
7720
- if (ts11.isBindingElement(parent) || ts11.isPropertyAccessExpression(parent) || ts11.isShorthandPropertyAssignment(parent)) {
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 (ts11.isParenthesizedExpression(expression)) expression = expression.expression;
7731
- if (ts11.isJsxFragment(expression)) {
8217
+ while (ts13.isParenthesizedExpression(expression)) expression = expression.expression;
8218
+ if (ts13.isJsxFragment(expression)) {
7732
8219
  const children = expression.children.filter(
7733
- (c) => !ts11.isJsxText(c) && !ts11.isJsxSpreadAttribute(c)
8220
+ (c) => !ts13.isJsxText(c) && !ts13.isJsxSpreadAttribute(c)
7734
8221
  );
7735
8222
  return { root: expression, children };
7736
8223
  }
7737
- if (ts11.isJsxElement(expression)) {
8224
+ if (ts13.isJsxElement(expression)) {
7738
8225
  const children = expression.children.filter(
7739
- (c) => !ts11.isJsxText(c) && !ts11.isJsxSpreadAttribute(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 (ts11.isFunctionDeclaration(node) || ts11.isClassDeclaration(node)) return;
7754
- ts11.forEachChild(node, visit);
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 = path51.resolve(context.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 = ts11.isFunctionDeclaration(declaration) ? declaration.body : void 0;
7794
- if (!body || !ts11.isBlock(body)) return void 0;
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 && (ts11.isFunctionLike(node) || ts11.isClassLike(node))) return;
7798
- if (ts11.isReturnStatement(node)) returns.push(node);
7799
- ts11.forEachChild(node, visit);
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 || !ts11.isExpression(single.expression)) return void 0;
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 && (ts11.isFunctionDeclaration(node) || ts11.isClassDeclaration(node))) return;
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 (!ts11.isSourceFile(current)) {
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
- ts11.forEachChild(node, visit);
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 path52 from "path";
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 = path52.resolve(context.filename);
8375
+ const filename = path55.resolve(context.filename);
7889
8376
  if (!MODULE_EXTENSION.test(filename)) return {};
7890
- const relative = path52.relative(context.cwd, filename).replace(/\\/g, "/");
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 = path52.basename(filename);
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 path53 from "path";
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 = path53.resolve(context.filename);
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 path54 from "path";
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 = path54.resolve(context.filename);
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 path55 from "path";
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 = path55.resolve(context.filename);
8054
- const baseName = path55.basename(filename);
8540
+ const filename = path58.resolve(context.filename);
8541
+ const baseName = path58.basename(filename);
8055
8542
  if (!INDEX_NAMES2.has(baseName)) return {};
8056
- const folder = path55.basename(path55.dirname(filename));
8543
+ const folder = path58.basename(path58.dirname(filename));
8057
8544
  if (!SUPPORT_FOLDERS4.has(folder)) return {};
8058
- const directory = path55.dirname(filename);
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(path55.basename(specifier));
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 path58 from "path";
8742
+ import path61 from "path";
8256
8743
 
8257
8744
  // eslint/rules/tailwind/source-files.ts
8258
- import { readdirSync as readdirSync3, readFileSync as readFileSync10, statSync as statSync3 } from "fs";
8259
- import path56 from "path";
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 = path56.join(dir, entry);
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(path56.extname(entry)) ? [entryPath] : [];
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 = readFileSync10(file, "utf8");
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 path57 from "path";
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 path57.resolve(spec);
8318
- if (spec.startsWith("./") || spec.startsWith("../")) return path57.resolve(path57.dirname(fromFile), spec);
8319
- if (spec.startsWith("@/")) return path57.resolve(sourceRoot, spec.slice(2));
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) => path57.normalize(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(path57.normalize(global));
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 = path57.normalize(target);
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 = path57.normalize(target);
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 = path58.join("app", "styles");
8356
- var GLOBAL_STYLESHEET_PATH = path58.join(APP_STYLES_DIR, "globals.css");
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 = path58.normalize(path58.resolve(context.filename));
8383
- const relative = path58.relative(sourceRoot, current);
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 = path58.basename(current);
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}${path58.sep}`);
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 path59 from "path";
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 = path59.resolve(context.filename);
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 readFileSync11, statSync as statSync6 } from "fs";
9535
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync6 } from "fs";
9049
9536
  import { createRequire } from "module";
9050
- import path60 from "path";
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 = path60.join(dir, entry);
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 path60.extname(entry) === ".css" ? [entryPath] : [];
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 = path60.dirname(fromFile);
9310
- while (directory !== path60.dirname(directory)) {
9311
- const packageRoot = path60.join(directory, "node_modules", packageName);
9312
- const manifestPath = path60.join(packageRoot, "package.json");
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 = readFileSync11(manifestPath, "utf8");
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 = path60.resolve(packageRoot, target);
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 = path60.dirname(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 = readFileSync11(file, "utf8");
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 = readFileSync11(file, "utf8");
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 path61 from "path";
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 = path61.resolve(context.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 = path61.basename(filename, path61.extname(filename));
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}.${path61.extname(filename).slice(1)}.`
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 path62 from "path";
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 = path62.resolve(context.filename);
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 readFileSync12 } from "fs";
9651
- import path63 from "path";
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 memberName6(member) {
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) => memberName6(member) === "dependencies");
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) => memberName6(member) === name);
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 = path63.dirname(path63.resolve(context.filename));
9685
- const configPath = path63.join(projectRoot, "vulyk.config.ts");
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 = readFileSync12(configPath, "utf8");
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 = path63.join(projectRoot, "AGENTS.md");
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 memberName7(member) {
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) => memberName7(member) === sectionName);
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) => memberName7(member) === "vulyk");
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 DOC6 = "docs/pasika-adoption-guide/rules/with-response-helper-rule.md";
9772
- var DECLARED3 = `A repository must not declare its own ${HELPER3}; import it from ${ENTRY3}. See ${DOC6}`;
9773
- var IMPORTED3 = `${HELPER3} must be imported from ${ENTRY3}. See ${DOC6}`;
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 path64 from "path";
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 = path64.resolve(context.filename);
9830
- const basename = path64.basename(filename);
10316
+ const filename = path67.resolve(context.filename);
10317
+ const basename = path67.basename(filename);
9831
10318
  if (!ESLINT_CONFIG.test(basename)) return {};
9832
- const projectRoot = path64.dirname(filename);
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 = path64.join(projectRoot, "tsconfig.json");
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(path64.join(projectRoot, name)));
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(path64.join(projectRoot, prettierConfigFile), "utf8");
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 DOC7 = "docs/pasika-adoption-guide/rules/zod-fetch-helper-rule.md";
9895
- var FETCHED = `fetch must not be called; make the request through ${HELPER4} from ${ENTRY4}. See ${DOC7}`;
9896
- var DECLARED4 = `A file must not declare its own ${HELPER4}; import it from ${ENTRY4}. See ${DOC7}`;
9897
- var IMPORTED4 = `${HELPER4} must be imported from ${ENTRY4}. See ${DOC7}`;
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 readFileSync13 } from "fs";
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(readFileSync13(packagePath, "utf8"));
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,