pasika 0.10.57 → 0.10.59

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.
@@ -259,6 +259,7 @@ declare const pasikaPlugin: {
259
259
  "locale-placement": eslint.Rule.RuleModule;
260
260
  "sole-state-owner": eslint.Rule.RuleModule;
261
261
  "locale-key-shape": eslint.Rule.RuleModule;
262
+ "repeated-numeric-value": eslint.Rule.RuleModule;
262
263
  "repeated-structure": eslint.Rule.RuleModule;
263
264
  };
264
265
  };
@@ -38,8 +38,8 @@ function memberPropertyName(node) {
38
38
  }
39
39
  return void 0;
40
40
  }
41
- function importedContractMember(expression, propertyName3, imports) {
42
- if (expression?.type !== "MemberExpression" || memberPropertyName(expression) !== propertyName3 || expression.object.type !== "Identifier" || !imports.has(expression.object.name)) {
41
+ function importedContractMember(expression, propertyName4, imports) {
42
+ if (expression?.type !== "MemberExpression" || memberPropertyName(expression) !== propertyName4 || expression.object.type !== "Identifier" || !imports.has(expression.object.name)) {
43
43
  return void 0;
44
44
  }
45
45
  return expression.object.name;
@@ -278,10 +278,29 @@ import path3 from "path";
278
278
  import ts from "typescript";
279
279
  var isPascalCase = (name) => /^[A-Z][A-Za-z0-9]*$/.test(name);
280
280
  var isHookName = (name) => /^use[A-Z]/.test(name);
281
- var isSchemaName = (name) => /[Ss]chema$/.test(name);
281
+ var isSchemaName = (name) => /(?:[Ss]chema|ApiContract)$/.test(name);
282
282
  function lineOf(sourceFile, node) {
283
283
  return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
284
284
  }
285
+ function numericLiteralValue(node) {
286
+ if (!node) return void 0;
287
+ if (ts.isNumericLiteral(node)) return Number(node.text.replaceAll("_", ""));
288
+ if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(node.operand)) {
289
+ return -Number(node.operand.text.replaceAll("_", ""));
290
+ }
291
+ return void 0;
292
+ }
293
+ function semanticName(name) {
294
+ const parts = name.replace(/(?<lower>[a-z0-9])(?<upper>[A-Z])/g, "$<lower> $<upper>").replace(/[_-]+/g, " ").toLowerCase().split(/\s+/).filter(Boolean);
295
+ const last = parts.at(-1);
296
+ if (last === "width" || last === "height" || last === "fps") return last;
297
+ if (parts.includes("duration")) return "duration";
298
+ return parts.join(" ");
299
+ }
300
+ function propertyName(node) {
301
+ if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node)) return node.text;
302
+ return void 0;
303
+ }
285
304
  function returnsJsx(node) {
286
305
  let found = false;
287
306
  const visit = (child) => {
@@ -317,6 +336,31 @@ function parseModule(file) {
317
336
  const imports = [];
318
337
  const reexports = [];
319
338
  const exports = [];
339
+ const namedNumericLiterals = [];
340
+ const addNamedNumericLiteral = (name, value, node) => {
341
+ namedNumericLiterals.push({
342
+ name,
343
+ semanticName: semanticName(name),
344
+ value,
345
+ line: lineOf(sourceFile, node)
346
+ });
347
+ };
348
+ const collectNamedNumericLiterals = (node) => {
349
+ if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
350
+ const value = numericLiteralValue(node.initializer);
351
+ if (value !== void 0) addNamedNumericLiteral(node.name.text, value, node.initializer ?? node);
352
+ } else if (ts.isPropertyAssignment(node)) {
353
+ const name = propertyName(node.name);
354
+ const value = numericLiteralValue(node.initializer);
355
+ if (name && value !== void 0) addNamedNumericLiteral(name, value, node.initializer);
356
+ } else if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name) && node.initializer && ts.isJsxExpression(node.initializer)) {
357
+ const expression = node.initializer.expression;
358
+ const value = expression ? numericLiteralValue(expression) : void 0;
359
+ if (value !== void 0 && expression) addNamedNumericLiteral(node.name.text, value, expression);
360
+ }
361
+ ts.forEachChild(node, collectNamedNumericLiterals);
362
+ };
363
+ collectNamedNumericLiterals(sourceFile);
320
364
  const addImport = (specifierNode, names, node) => {
321
365
  if (!ts.isStringLiteral(specifierNode)) return;
322
366
  imports.push({ specifier: specifierNode.text, names, line: lineOf(sourceFile, node) });
@@ -398,7 +442,7 @@ function parseModule(file) {
398
442
  });
399
443
  }
400
444
  }
401
- return { file: path3.resolve(file), imports, reexports, exports };
445
+ return { file: path3.resolve(file), imports, reexports, exports, namedNumericLiterals };
402
446
  }
403
447
 
404
448
  // eslint/rules/project-root.ts
@@ -4864,7 +4908,7 @@ function isStaticValue(value) {
4864
4908
  }
4865
4909
  return false;
4866
4910
  }
4867
- function propertyName(property) {
4911
+ function propertyName2(property) {
4868
4912
  if (!property.computed && property.key.type === "Identifier") return property.key.name;
4869
4913
  if (property.key.type === "Literal" && typeof property.key.value === "string") return property.key.value;
4870
4914
  return void 0;
@@ -4872,7 +4916,7 @@ function propertyName(property) {
4872
4916
  function findStaticDeclaration(expression) {
4873
4917
  for (const property of expression.properties) {
4874
4918
  if (property.type !== "Property" || property.kind !== "init") continue;
4875
- const name = propertyName(property);
4919
+ const name = propertyName2(property);
4876
4920
  if (!name) continue;
4877
4921
  if (isStaticValue(property.value)) return name;
4878
4922
  }
@@ -5447,7 +5491,7 @@ function isZodCall(node, method) {
5447
5491
  const { callee } = node;
5448
5492
  return callee?.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "z" && callee.property.type === "Identifier" && callee.property.name === method;
5449
5493
  }
5450
- function propertyName2(property) {
5494
+ function propertyName3(property) {
5451
5495
  if (property.computed) return void 0;
5452
5496
  if (property.key.type === "Identifier") return property.key.name;
5453
5497
  if (property.key.type === "Literal" && typeof property.key.value === "string") return property.key.value;
@@ -5458,7 +5502,7 @@ function rawZodDiscriminantLiteral(schemaCall, discriminator) {
5458
5502
  const shape = schemaCall.arguments[0];
5459
5503
  if (shape?.type !== "ObjectExpression") return void 0;
5460
5504
  for (const property of shape.properties) {
5461
- if (property.type !== "Property" || propertyName2(property) !== discriminator) continue;
5505
+ if (property.type !== "Property" || propertyName3(property) !== discriminator) continue;
5462
5506
  if (property.value.type !== "CallExpression" || !isZodCall(property.value, "literal")) return void 0;
5463
5507
  const literal = property.value.arguments[0];
5464
5508
  if (literal?.type === "Literal" && (typeof literal.value === "string" || typeof literal.value === "number")) {
@@ -5679,6 +5723,70 @@ var pureFunctionExtractRule = {
5679
5723
  }
5680
5724
  };
5681
5725
 
5726
+ // eslint/rules/repeated-numeric-value.ts
5727
+ import path44 from "path";
5728
+ var ignoredValues = /* @__PURE__ */ new Set([-1, 0, 1]);
5729
+ function isNonProductionFile(file, sourceRoot) {
5730
+ const relative = path44.relative(sourceRoot, file);
5731
+ const segments = relative.split(path44.sep);
5732
+ const basename = path44.basename(file);
5733
+ return /\.(?:test|spec|mock)\.[^.]+$/.test(basename) || segments.some((segment) => segment === "__tests__" || segment === "__mocks__" || segment === "mocks");
5734
+ }
5735
+ function isCanonicalConstantFile(file, sourceRoot) {
5736
+ const segments = path44.relative(sourceRoot, file).split(path44.sep);
5737
+ return segments.includes("constants") || segments[0] === "config";
5738
+ }
5739
+ function groupKey(literal) {
5740
+ return `${literal.semanticName}\0${String(literal.value)}`;
5741
+ }
5742
+ var repeatedNumericValueRule = {
5743
+ meta: {
5744
+ schema: [],
5745
+ type: "problem",
5746
+ docs: {
5747
+ description: "Require repeated named numeric values across production files to use one extracted constant or enum."
5748
+ }
5749
+ },
5750
+ create(context) {
5751
+ const sourceRoot = sourceRootOf(context);
5752
+ const file = path44.resolve(context.filename);
5753
+ if (isNonProductionFile(file, sourceRoot) || isCanonicalConstantFile(file, sourceRoot)) return {};
5754
+ const index = getProjectIndex(sourceRoot);
5755
+ if (!index) return {};
5756
+ const currentModule = index.modules.get(file);
5757
+ if (!currentModule) return {};
5758
+ const filesByGroup = /* @__PURE__ */ new Map();
5759
+ for (const [moduleFile, parsedModule] of index.modules) {
5760
+ if (isNonProductionFile(moduleFile, sourceRoot)) continue;
5761
+ for (const literal of parsedModule.namedNumericLiterals) {
5762
+ if (ignoredValues.has(literal.value)) continue;
5763
+ const key = groupKey(literal);
5764
+ const files = filesByGroup.get(key) ?? /* @__PURE__ */ new Set();
5765
+ files.add(moduleFile);
5766
+ filesByGroup.set(key, files);
5767
+ }
5768
+ }
5769
+ return {
5770
+ Program(node) {
5771
+ const reported = /* @__PURE__ */ new Set();
5772
+ for (const literal of currentModule.namedNumericLiterals) {
5773
+ if (ignoredValues.has(literal.value)) continue;
5774
+ const key = groupKey(literal);
5775
+ if (reported.has(key)) continue;
5776
+ const files = filesByGroup.get(key);
5777
+ if (!files || files.size < 2) continue;
5778
+ reported.add(key);
5779
+ context.report({
5780
+ node,
5781
+ loc: { line: literal.line, column: 0 },
5782
+ 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`
5783
+ });
5784
+ }
5785
+ }
5786
+ };
5787
+ }
5788
+ };
5789
+
5682
5790
  // eslint/rules/repeated-structure.ts
5683
5791
  function nodeKind(node) {
5684
5792
  return node.type;
@@ -5861,7 +5969,7 @@ var repeatedStructureRule = {
5861
5969
 
5862
5970
  // eslint/rules/require-barrel-star-exports.ts
5863
5971
  import fs5 from "fs";
5864
- import path44 from "path";
5972
+ import path45 from "path";
5865
5973
  var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
5866
5974
  var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
5867
5975
  var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
@@ -5869,9 +5977,9 @@ function resolveSiblingModule(indexFile, specifier) {
5869
5977
  if (!specifier.startsWith("./")) return void 0;
5870
5978
  const relative = specifier.slice(2);
5871
5979
  if (!relative || relative.includes("/")) return void 0;
5872
- const directory = path44.dirname(indexFile);
5873
- const direct = path44.resolve(directory, relative);
5874
- const candidates = path44.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
5980
+ const directory = path45.dirname(indexFile);
5981
+ const direct = path45.resolve(directory, relative);
5982
+ const candidates = path45.extname(direct) ? [direct] : MODULE_EXTENSIONS3.map((extension) => `${direct}${extension}`);
5875
5983
  return candidates.find((candidate) => fs5.existsSync(candidate) && fs5.statSync(candidate).isFile());
5876
5984
  }
5877
5985
  var requireBarrelStarExportsRule = {
@@ -5884,9 +5992,9 @@ var requireBarrelStarExportsRule = {
5884
5992
  fixable: "code"
5885
5993
  },
5886
5994
  create(context) {
5887
- const filename = path44.resolve(context.filename);
5888
- if (!INDEX_NAMES.has(path44.basename(filename))) return {};
5889
- if (!SUPPORT_FOLDERS3.has(path44.basename(path44.dirname(filename)))) return {};
5995
+ const filename = path45.resolve(context.filename);
5996
+ if (!INDEX_NAMES.has(path45.basename(filename))) return {};
5997
+ if (!SUPPORT_FOLDERS3.has(path45.basename(path45.dirname(filename)))) return {};
5890
5998
  return {
5891
5999
  ExportNamedDeclaration(node) {
5892
6000
  const sourceNode = node.source;
@@ -5939,7 +6047,7 @@ var requireBarrelStarExportsRule = {
5939
6047
  };
5940
6048
 
5941
6049
  // eslint/rules/root-support-placement.ts
5942
- import path45 from "path";
6050
+ import path46 from "path";
5943
6051
  function isSupportFolder(value) {
5944
6052
  return value === "utils" || value === "types" || value === "schemas" || value === "constants";
5945
6053
  }
@@ -5972,7 +6080,7 @@ var rootSupportPlacementRule = {
5972
6080
  },
5973
6081
  create(context) {
5974
6082
  const sourceRoot = sourceRootOf(context);
5975
- const file = path45.resolve(context.filename);
6083
+ const file = path46.resolve(context.filename);
5976
6084
  const segments = segmentsOf(file, sourceRoot);
5977
6085
  const folderSegments = folderSegmentsOf(file, sourceRoot);
5978
6086
  const supportFolder = folderSegments[folderSegments.length - 1];
@@ -6012,7 +6120,7 @@ var rootSupportPlacementRule = {
6012
6120
  };
6013
6121
 
6014
6122
  // eslint/rules/route-handler-shape.ts
6015
- import path46 from "path";
6123
+ import path47 from "path";
6016
6124
  import ts7 from "typescript";
6017
6125
  var HTTP_METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
6018
6126
  var REQUIRED_BOUNDARY = "withResponse";
@@ -6097,7 +6205,7 @@ var routeHandlerShapeRule = {
6097
6205
  }
6098
6206
  },
6099
6207
  create(context) {
6100
- if (path46.basename(context.filename) !== "route.ts") return {};
6208
+ if (path47.basename(context.filename) !== "route.ts") return {};
6101
6209
  const sourceText = context.sourceCode.text;
6102
6210
  function reportUnwrapped(node, name) {
6103
6211
  context.report({
@@ -6156,7 +6264,7 @@ var routeHandlerShapeRule = {
6156
6264
  };
6157
6265
 
6158
6266
  // eslint/rules/schema-casing.ts
6159
- import path47 from "path";
6267
+ import path48 from "path";
6160
6268
  function isCamelCase(name) {
6161
6269
  return /^[a-z][a-zA-Z0-9]*$/.test(name);
6162
6270
  }
@@ -6184,9 +6292,9 @@ var schemaCasingRule = {
6184
6292
  }
6185
6293
  },
6186
6294
  create(context) {
6187
- const filename = path47.resolve(context.filename);
6295
+ const filename = path48.resolve(context.filename);
6188
6296
  const sourceRoot = sourceRootOf(context);
6189
- if (!filename.startsWith(sourceRoot + path47.sep)) return {};
6297
+ if (!filename.startsWith(sourceRoot + path48.sep)) return {};
6190
6298
  let zodLocalName;
6191
6299
  return {
6192
6300
  ImportDeclaration(node) {
@@ -6218,7 +6326,7 @@ var schemaCasingRule = {
6218
6326
  };
6219
6327
 
6220
6328
  // eslint/rules/sole-state-owner.ts
6221
- import path48 from "path";
6329
+ import path49 from "path";
6222
6330
  import ts8 from "typescript";
6223
6331
  function findStateHooks(node) {
6224
6332
  const hooks = [];
@@ -6298,7 +6406,7 @@ var soleStateOwnerRule = {
6298
6406
  }
6299
6407
  },
6300
6408
  create(context) {
6301
- const filename = path48.resolve(context.filename);
6409
+ const filename = path49.resolve(context.filename);
6302
6410
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
6303
6411
  const text = context.sourceCode.text;
6304
6412
  const components = parseComponentInfo(text, filename);
@@ -6377,7 +6485,7 @@ function usesOutsideJsx(declaration, hook, children) {
6377
6485
  }
6378
6486
 
6379
6487
  // eslint/rules/source-under-src.ts
6380
- import path49 from "path";
6488
+ import path50 from "path";
6381
6489
  var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
6382
6490
  ".agents",
6383
6491
  ".cache",
@@ -6418,14 +6526,14 @@ var sourceUnderSrcRule = {
6418
6526
  }
6419
6527
  },
6420
6528
  create(context) {
6421
- const filename = path49.resolve(context.filename);
6529
+ const filename = path50.resolve(context.filename);
6422
6530
  if (!MODULE_EXTENSION.test(filename)) return {};
6423
- const relative = path49.relative(context.cwd, filename).replace(/\\/g, "/");
6531
+ const relative = path50.relative(context.cwd, filename).replace(/\\/g, "/");
6424
6532
  if (relative === "src" || relative.startsWith("src/")) return {};
6425
6533
  const topLevel = relative.split("/")[0] ?? "";
6426
6534
  if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
6427
6535
  if (!relative.includes("/")) {
6428
- const basename = path49.basename(filename);
6536
+ const basename = path50.basename(filename);
6429
6537
  if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
6430
6538
  }
6431
6539
  return {
@@ -6441,7 +6549,7 @@ var sourceUnderSrcRule = {
6441
6549
  };
6442
6550
 
6443
6551
  // eslint/rules/stay-flat.ts
6444
- import path50 from "path";
6552
+ import path51 from "path";
6445
6553
  var stayFlatRule = {
6446
6554
  meta: {
6447
6555
  schema: [],
@@ -6452,7 +6560,7 @@ var stayFlatRule = {
6452
6560
  },
6453
6561
  create(context) {
6454
6562
  const sourceRoot = sourceRootOf(context);
6455
- const file = path50.resolve(context.filename);
6563
+ const file = path51.resolve(context.filename);
6456
6564
  const segments = segmentsOf(file, sourceRoot);
6457
6565
  if (segments.length !== 3 || segments[0] !== "features") return {};
6458
6566
  const index = getProjectIndex(sourceRoot);
@@ -6492,7 +6600,7 @@ var stayFlatRule = {
6492
6600
  };
6493
6601
 
6494
6602
  // eslint/rules/support-file-placement.ts
6495
- import path51 from "path";
6603
+ import path52 from "path";
6496
6604
  var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
6497
6605
  var EXPORT_KIND_BY_SUPPORT_FOLDER = /* @__PURE__ */ new Map([
6498
6606
  ["constants", "constant"],
@@ -6517,7 +6625,7 @@ var supportFilePlacementRule = {
6517
6625
  },
6518
6626
  create(context) {
6519
6627
  const sourceRoot = sourceRootOf(context);
6520
- const supportFile = path51.resolve(context.filename);
6628
+ const supportFile = path52.resolve(context.filename);
6521
6629
  const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
6522
6630
  const supportFolder = currentFolder[currentFolder.length - 1];
6523
6631
  if (supportFolder === void 0 || !SUPPORT_FOLDERS.has(supportFolder)) return {};
@@ -6571,7 +6679,7 @@ var supportFilePlacementRule = {
6571
6679
 
6572
6680
  // eslint/rules/support-folder-shape.ts
6573
6681
  import fs6 from "fs";
6574
- import path52 from "path";
6682
+ import path53 from "path";
6575
6683
  var SUPPORT_FOLDERS4 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
6576
6684
  var INDEX_NAMES2 = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
6577
6685
  var supportFolderShapeRule = {
@@ -6583,12 +6691,12 @@ var supportFolderShapeRule = {
6583
6691
  }
6584
6692
  },
6585
6693
  create(context) {
6586
- const filename = path52.resolve(context.filename);
6587
- const baseName = path52.basename(filename);
6694
+ const filename = path53.resolve(context.filename);
6695
+ const baseName = path53.basename(filename);
6588
6696
  if (!INDEX_NAMES2.has(baseName)) return {};
6589
- const folder = path52.basename(path52.dirname(filename));
6697
+ const folder = path53.basename(path53.dirname(filename));
6590
6698
  if (!SUPPORT_FOLDERS4.has(folder)) return {};
6591
- const directory = path52.dirname(filename);
6699
+ const directory = path53.dirname(filename);
6592
6700
  let entries;
6593
6701
  try {
6594
6702
  entries = fs6.readdirSync(directory);
@@ -6606,7 +6714,7 @@ var supportFolderShapeRule = {
6606
6714
  for (const match of source.matchAll(exportPattern)) {
6607
6715
  hasAnyReExport = true;
6608
6716
  const specifier = match.groups?.specifier;
6609
- if (specifier?.startsWith(".")) exportedFiles.add(path52.basename(specifier));
6717
+ if (specifier?.startsWith(".")) exportedFiles.add(path53.basename(specifier));
6610
6718
  }
6611
6719
  const guide = `docs/next-codebase-guide/rules/${folder === "constants" ? "constants" : "types-and-schemas"}-rule.md`;
6612
6720
  if (siblingModules.length === 0) {
@@ -6785,11 +6893,11 @@ var baseLayerPairRule = {
6785
6893
 
6786
6894
  // eslint/rules/tailwind/css-entry-point.ts
6787
6895
  import { statSync as statSync4 } from "fs";
6788
- import path55 from "path";
6896
+ import path56 from "path";
6789
6897
 
6790
6898
  // eslint/rules/tailwind/source-files.ts
6791
6899
  import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync3 } from "fs";
6792
- import path53 from "path";
6900
+ import path54 from "path";
6793
6901
  var CSS_EXTENSIONS = [".css"];
6794
6902
  var MODULE_EXTENSIONS4 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
6795
6903
  var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS4, ...CSS_EXTENSIONS];
@@ -6802,7 +6910,7 @@ function findFiles(dir, extensions) {
6802
6910
  }
6803
6911
  return entries.flatMap((entry) => {
6804
6912
  if (entry.startsWith(".") || entry === "node_modules") return [];
6805
- const entryPath = path53.join(dir, entry);
6913
+ const entryPath = path54.join(dir, entry);
6806
6914
  let stats;
6807
6915
  try {
6808
6916
  stats = statSync3(entryPath);
@@ -6810,7 +6918,7 @@ function findFiles(dir, extensions) {
6810
6918
  return [];
6811
6919
  }
6812
6920
  if (stats.isDirectory()) return findFiles(entryPath, extensions);
6813
- return extensions.includes(path53.extname(entry)) ? [entryPath] : [];
6921
+ return extensions.includes(path54.extname(entry)) ? [entryPath] : [];
6814
6922
  });
6815
6923
  }
6816
6924
  function cachedTextReader() {
@@ -6833,7 +6941,7 @@ function escapeRegExp(text) {
6833
6941
  }
6834
6942
 
6835
6943
  // eslint/rules/tailwind/stylesheet-graph.ts
6836
- import path54 from "path";
6944
+ import path55 from "path";
6837
6945
  function registersTailwind(text) {
6838
6946
  return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
6839
6947
  }
@@ -6847,25 +6955,25 @@ function moduleImports(text, fileName) {
6847
6955
  return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
6848
6956
  }
6849
6957
  function resolveSpecifier2(fromFile, spec, sourceRoot) {
6850
- if (spec.startsWith("/")) return path54.resolve(spec);
6851
- if (spec.startsWith("./") || spec.startsWith("../")) return path54.resolve(path54.dirname(fromFile), spec);
6852
- if (spec.startsWith("@/")) return path54.resolve(sourceRoot, spec.slice(2));
6958
+ if (spec.startsWith("/")) return path55.resolve(spec);
6959
+ if (spec.startsWith("./") || spec.startsWith("../")) return path55.resolve(path55.dirname(fromFile), spec);
6960
+ if (spec.startsWith("@/")) return path55.resolve(sourceRoot, spec.slice(2));
6853
6961
  return void 0;
6854
6962
  }
6855
6963
  function buildStylesheetGraph(options) {
6856
6964
  const { cssFiles, sourceRoot, textOf } = options;
6857
- const cssSet = new Set(cssFiles.map((file) => path54.normalize(file)));
6965
+ const cssSet = new Set(cssFiles.map((file) => path55.normalize(file)));
6858
6966
  const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
6859
6967
  const reachable = /* @__PURE__ */ new Set();
6860
6968
  const queue = [...globals];
6861
- for (const global of globals) reachable.add(path54.normalize(global));
6969
+ for (const global of globals) reachable.add(path55.normalize(global));
6862
6970
  while (queue.length > 0) {
6863
6971
  const from = queue.shift();
6864
6972
  if (!from) continue;
6865
6973
  for (const spec of importedSpecifiers(textOf(from))) {
6866
6974
  const target = resolveSpecifier2(from, spec, sourceRoot);
6867
6975
  if (!target) continue;
6868
- const normalized = path54.normalize(target);
6976
+ const normalized = path55.normalize(target);
6869
6977
  if (cssSet.has(normalized) && !reachable.has(normalized)) {
6870
6978
  reachable.add(normalized);
6871
6979
  queue.push(normalized);
@@ -6877,7 +6985,7 @@ function buildStylesheetGraph(options) {
6877
6985
  for (const spec of importedSpecifiers(textOf(global))) {
6878
6986
  const target = resolveSpecifier2(global, spec, sourceRoot);
6879
6987
  if (!target) continue;
6880
- const normalized = path54.normalize(target);
6988
+ const normalized = path55.normalize(target);
6881
6989
  if (cssSet.has(normalized)) directChildren.add(normalized);
6882
6990
  }
6883
6991
  }
@@ -6885,8 +6993,8 @@ function buildStylesheetGraph(options) {
6885
6993
  }
6886
6994
 
6887
6995
  // eslint/rules/tailwind/css-entry-point.ts
6888
- var APP_STYLES_DIR = path55.join("app", "styles");
6889
- var GLOBAL_STYLESHEET_PATH = path55.join(APP_STYLES_DIR, "globals.css");
6996
+ var APP_STYLES_DIR = path56.join("app", "styles");
6997
+ var GLOBAL_STYLESHEET_PATH = path56.join(APP_STYLES_DIR, "globals.css");
6890
6998
  var cssEntryPointRule = {
6891
6999
  meta: {
6892
7000
  schema: [],
@@ -6912,8 +7020,8 @@ var cssEntryPointRule = {
6912
7020
  return {
6913
7021
  "StyleSheet:exit"(node) {
6914
7022
  if (globals.length === 0) return;
6915
- const current = path55.normalize(path55.resolve(context.filename));
6916
- const relative = path55.relative(sourceRoot, current);
7023
+ const current = path56.normalize(path56.resolve(context.filename));
7024
+ const relative = path56.relative(sourceRoot, current);
6917
7025
  if (globals.includes(current)) {
6918
7026
  if (globals.length > 1) {
6919
7027
  context.report({
@@ -6929,7 +7037,7 @@ var cssEntryPointRule = {
6929
7037
  });
6930
7038
  return;
6931
7039
  }
6932
- const basename = path55.basename(current);
7040
+ const basename = path56.basename(current);
6933
7041
  const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
6934
7042
  if (importCount !== 1) {
6935
7043
  context.report({
@@ -6939,7 +7047,7 @@ var cssEntryPointRule = {
6939
7047
  }
6940
7048
  return;
6941
7049
  }
6942
- const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path55.sep}`);
7050
+ const isInAppStyles = relative === APP_STYLES_DIR || relative.startsWith(`${APP_STYLES_DIR}${path56.sep}`);
6943
7051
  if (!isInAppStyles) {
6944
7052
  context.report({
6945
7053
  node,
@@ -7428,7 +7536,7 @@ var tailwindRules = {
7428
7536
  };
7429
7537
 
7430
7538
  // eslint/rules/type-extraction.ts
7431
- import path56 from "path";
7539
+ import path57 from "path";
7432
7540
  var typeExtractionRule = {
7433
7541
  meta: {
7434
7542
  schema: [],
@@ -7439,7 +7547,7 @@ var typeExtractionRule = {
7439
7547
  },
7440
7548
  create(context) {
7441
7549
  const sourceRoot = sourceRootOf(context);
7442
- const file = path56.resolve(context.filename);
7550
+ const file = path57.resolve(context.filename);
7443
7551
  const segments = segmentsOf(file, sourceRoot);
7444
7552
  if (segments.length === 0) return {};
7445
7553
  const index = getProjectIndex(sourceRoot);
@@ -7574,7 +7682,7 @@ var uiStateRule = {
7574
7682
  // eslint/rules/unknown-utility.ts
7575
7683
  import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
7576
7684
  import { createRequire } from "module";
7577
- import path57 from "path";
7685
+ import path58 from "path";
7578
7686
  var PREFIX_NAMESPACES = {
7579
7687
  bg: ["color"],
7580
7688
  text: ["color", "text"],
@@ -7814,7 +7922,7 @@ function stylesheetFiles(dir) {
7814
7922
  }
7815
7923
  return entries.flatMap((entry) => {
7816
7924
  if (entry.startsWith(".") || entry === "node_modules") return [];
7817
- const entryPath = path57.join(dir, entry);
7925
+ const entryPath = path58.join(dir, entry);
7818
7926
  let stats;
7819
7927
  try {
7820
7928
  stats = statSync6(entryPath);
@@ -7822,7 +7930,7 @@ function stylesheetFiles(dir) {
7822
7930
  return [];
7823
7931
  }
7824
7932
  if (stats.isDirectory()) return stylesheetFiles(entryPath);
7825
- return path57.extname(entry) === ".css" ? [entryPath] : [];
7933
+ return path58.extname(entry) === ".css" ? [entryPath] : [];
7826
7934
  });
7827
7935
  }
7828
7936
  function packageNameOf(specifier) {
@@ -7833,10 +7941,10 @@ function packageNameOf(specifier) {
7833
7941
  function resolvePackageStylesheet(fromFile, specifier) {
7834
7942
  const packageName = packageNameOf(specifier);
7835
7943
  if (!packageName || packageName === "tailwindcss") return void 0;
7836
- let directory = path57.dirname(fromFile);
7837
- while (directory !== path57.dirname(directory)) {
7838
- const packageRoot = path57.join(directory, "node_modules", packageName);
7839
- const manifestPath = path57.join(packageRoot, "package.json");
7944
+ let directory = path58.dirname(fromFile);
7945
+ while (directory !== path58.dirname(directory)) {
7946
+ const packageRoot = path58.join(directory, "node_modules", packageName);
7947
+ const manifestPath = path58.join(packageRoot, "package.json");
7840
7948
  if (existsSync6(manifestPath)) {
7841
7949
  try {
7842
7950
  const manifest = readFileSync10(manifestPath, "utf8");
@@ -7844,13 +7952,13 @@ function resolvePackageStylesheet(fromFile, specifier) {
7844
7952
  const main = /"main"\s*:\s*"(?<file>[^"]+\.css)"/.exec(manifest)?.groups?.file;
7845
7953
  const target = stylesheet ?? main;
7846
7954
  if (!target) return void 0;
7847
- const resolved = path57.resolve(packageRoot, target);
7955
+ const resolved = path58.resolve(packageRoot, target);
7848
7956
  return existsSync6(resolved) ? resolved : void 0;
7849
7957
  } catch {
7850
7958
  return void 0;
7851
7959
  }
7852
7960
  }
7853
- directory = path57.dirname(directory);
7961
+ directory = path58.dirname(directory);
7854
7962
  }
7855
7963
  return void 0;
7856
7964
  }
@@ -8101,7 +8209,7 @@ var unknownUtilityRule = {
8101
8209
  };
8102
8210
 
8103
8211
  // eslint/rules/util-file-name.ts
8104
- import path58 from "path";
8212
+ import path59 from "path";
8105
8213
  function toKebabCase2(value) {
8106
8214
  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();
8107
8215
  }
@@ -8114,7 +8222,7 @@ var utilFileNameRule = {
8114
8222
  }
8115
8223
  },
8116
8224
  create(context) {
8117
- const filename = path58.resolve(context.filename);
8225
+ const filename = path59.resolve(context.filename);
8118
8226
  const segments = filename.replace(/\\/g, "/").split("/");
8119
8227
  if (!segments.includes("utils")) return {};
8120
8228
  let module;
@@ -8128,13 +8236,13 @@ var utilFileNameRule = {
8128
8236
  const functionName = functions[0]?.name;
8129
8237
  if (!functionName) return {};
8130
8238
  const expected = toKebabCase2(functionName);
8131
- const actual = path58.basename(filename, path58.extname(filename));
8239
+ const actual = path59.basename(filename, path59.extname(filename));
8132
8240
  if (!expected || actual === expected) return {};
8133
8241
  return {
8134
8242
  Program(node) {
8135
8243
  context.report({
8136
8244
  node,
8137
- message: `A utility file exporting ${functionName} must be named ${expected}.${path58.extname(filename).slice(1)}.`
8245
+ message: `A utility file exporting ${functionName} must be named ${expected}.${path59.extname(filename).slice(1)}.`
8138
8246
  });
8139
8247
  }
8140
8248
  };
@@ -8142,7 +8250,7 @@ var utilFileNameRule = {
8142
8250
  };
8143
8251
 
8144
8252
  // eslint/rules/value-extraction.ts
8145
- import path59 from "path";
8253
+ import path60 from "path";
8146
8254
  var valueExtractionRule = {
8147
8255
  meta: {
8148
8256
  schema: [],
@@ -8153,7 +8261,7 @@ var valueExtractionRule = {
8153
8261
  },
8154
8262
  create(context) {
8155
8263
  const sourceRoot = sourceRootOf(context);
8156
- const file = path59.resolve(context.filename);
8264
+ const file = path60.resolve(context.filename);
8157
8265
  const segments = segmentsOf(file, sourceRoot);
8158
8266
  if (segments.length === 0 || segments[0] !== "app") return {};
8159
8267
  const index = getProjectIndex(sourceRoot);
@@ -8175,7 +8283,7 @@ var valueExtractionRule = {
8175
8283
 
8176
8284
  // eslint/rules/vulyk/tracked-docs.ts
8177
8285
  import { existsSync as existsSync7, readFileSync as readFileSync11 } from "fs";
8178
- import path60 from "path";
8286
+ import path61 from "path";
8179
8287
  var PASIKA_REPO = "Bredansky/pasika";
8180
8288
  var BASE_REQUIRED_TRACKED_DOCS = [
8181
8289
  { name: "documentation-guide", path: "docs/documentation-guide" },
@@ -8208,8 +8316,8 @@ var trackedDocsRule = {
8208
8316
  if (!context.filename.endsWith("package.json")) return;
8209
8317
  const root = node.body;
8210
8318
  if (root.type !== "Object") return;
8211
- const projectRoot = path60.dirname(path60.resolve(context.filename));
8212
- const configPath = path60.join(projectRoot, "vulyk.config.ts");
8319
+ const projectRoot = path61.dirname(path61.resolve(context.filename));
8320
+ const configPath = path61.join(projectRoot, "vulyk.config.ts");
8213
8321
  if (!existsSync7(configPath)) {
8214
8322
  context.report({
8215
8323
  node,
@@ -8234,7 +8342,7 @@ var trackedDocsRule = {
8234
8342
  });
8235
8343
  }
8236
8344
  }
8237
- const agentsPath = path60.join(projectRoot, "AGENTS.md");
8345
+ const agentsPath = path61.join(projectRoot, "AGENTS.md");
8238
8346
  if (!existsSync7(agentsPath)) {
8239
8347
  context.report({
8240
8348
  node,
@@ -8334,7 +8442,7 @@ var withResponseHelperRule = {
8334
8442
 
8335
8443
  // eslint/rules/zirka-baseline.ts
8336
8444
  import fs7 from "fs";
8337
- import path61 from "path";
8445
+ import path62 from "path";
8338
8446
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
8339
8447
  var PRETTIER_CONFIGS = [
8340
8448
  "prettier.config.mjs",
@@ -8353,10 +8461,10 @@ var zirkaBaselineRule = {
8353
8461
  }
8354
8462
  },
8355
8463
  create(context) {
8356
- const filename = path61.resolve(context.filename);
8357
- const basename = path61.basename(filename);
8464
+ const filename = path62.resolve(context.filename);
8465
+ const basename = path62.basename(filename);
8358
8466
  if (!ESLINT_CONFIG.test(basename)) return {};
8359
- const projectRoot = path61.dirname(filename);
8467
+ const projectRoot = path62.dirname(filename);
8360
8468
  const report3 = (message) => {
8361
8469
  context.report({
8362
8470
  node: context.sourceCode.ast,
@@ -8371,7 +8479,7 @@ var zirkaBaselineRule = {
8371
8479
  'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
8372
8480
  );
8373
8481
  }
8374
- const tsconfigPath = path61.join(projectRoot, "tsconfig.json");
8482
+ const tsconfigPath = path62.join(projectRoot, "tsconfig.json");
8375
8483
  if (!fs7.existsSync(tsconfigPath)) {
8376
8484
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
8377
8485
  } else {
@@ -8389,13 +8497,13 @@ var zirkaBaselineRule = {
8389
8497
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
8390
8498
  }
8391
8499
  }
8392
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path61.join(projectRoot, name)));
8500
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs7.existsSync(path62.join(projectRoot, name)));
8393
8501
  if (!prettierConfigFile) {
8394
8502
  report3(
8395
8503
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
8396
8504
  );
8397
8505
  } else {
8398
- const content = fs7.readFileSync(path61.join(projectRoot, prettierConfigFile), "utf8");
8506
+ const content = fs7.readFileSync(path62.join(projectRoot, prettierConfigFile), "utf8");
8399
8507
  if (!content.includes("zirka")) {
8400
8508
  report3(
8401
8509
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
@@ -8647,6 +8755,7 @@ var pasikaNextjsAppRules = {
8647
8755
  "locale-placement": localePlacementRule,
8648
8756
  "sole-state-owner": soleStateOwnerRule,
8649
8757
  "locale-key-shape": localeKeyShapeRule,
8758
+ "repeated-numeric-value": repeatedNumericValueRule,
8650
8759
  "repeated-structure": repeatedStructureRule
8651
8760
  };
8652
8761
  var pasikaPlugin = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.10.57",
3
+ "version": "0.10.59",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",