pasika 0.5.6 → 0.5.8

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.
@@ -123,8 +123,9 @@ function findSimpleRoot(component, _text, _filename) {
123
123
  ts.forEachChild(node, visit);
124
124
  };
125
125
  visit(body);
126
- if (returns.length !== 1) return void 0;
127
- const expression = returns[0]?.expression;
126
+ const rendered = returns.filter((statement) => statement.expression?.kind !== ts.SyntaxKind.NullKeyword);
127
+ if (rendered.length !== 1) return void 0;
128
+ const expression = rendered[0]?.expression;
128
129
  return expression && ts.isExpression(expression) ? rootFromExpression(expression) : void 0;
129
130
  }
130
131
  function getTestId(root) {
@@ -1355,6 +1356,16 @@ function isKebabCase2(str) {
1355
1356
  return /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(str);
1356
1357
  }
1357
1358
  var SUPPORT_FOLDERS = /* @__PURE__ */ new Set(["types", "schemas", "hooks", "constants", "utils", "config", "locales"]);
1359
+ function parentComponentName(dirPath, folderName) {
1360
+ const componentFile = path9.join(dirPath, `${folderName}.tsx`);
1361
+ if (!fs.existsSync(componentFile)) return void 0;
1362
+ try {
1363
+ const exports = parseModule(componentFile).exports;
1364
+ return exports.find((moduleExport) => moduleExport.kind === "component")?.name;
1365
+ } catch {
1366
+ return void 0;
1367
+ }
1368
+ }
1358
1369
  var enforceBarrelExportsRule = {
1359
1370
  meta: {
1360
1371
  schema: [],
@@ -1373,8 +1384,8 @@ var enforceBarrelExportsRule = {
1373
1384
  const parentFolderName = path9.basename(path9.dirname(dirPath));
1374
1385
  if (SUPPORT_FOLDERS.has(folderName)) return {};
1375
1386
  if (!isPascalCase4(folderName) && !isKebabCase2(folderName)) return {};
1376
- const matchingTsx = fs.existsSync(path9.join(dirPath, `${folderName}.tsx`)) ? folderName : null;
1377
- if (!matchingTsx) return {};
1387
+ const parentName = parentComponentName(dirPath, folderName);
1388
+ if (!parentName) return {};
1378
1389
  if (!isPascalCase4(parentFolderName) && !isKebabCase2(parentFolderName)) return {};
1379
1390
  const reExportedNames = /* @__PURE__ */ new Set();
1380
1391
  return {
@@ -1388,18 +1399,18 @@ var enforceBarrelExportsRule = {
1388
1399
  },
1389
1400
  "Program:exit"() {
1390
1401
  if (reExportedNames.size === 0) return;
1391
- if (!reExportedNames.has(matchingTsx)) {
1402
+ if (!reExportedNames.has(parentName)) {
1392
1403
  context.report({
1393
1404
  loc: { line: 1, column: 0 },
1394
- message: `index.ts in "${folderName}/" must re-export "${matchingTsx}". See docs/code-organization-guide/rules/folder-nesting-rule.md`
1405
+ message: `index.ts in "${folderName}/" must re-export "${parentName}". See docs/code-organization-guide/rules/folder-nesting-rule.md`
1395
1406
  });
1396
1407
  return;
1397
1408
  }
1398
- const nonParentExports = [...reExportedNames].filter((n) => n !== matchingTsx);
1409
+ const nonParentExports = [...reExportedNames].filter((n) => n !== parentName);
1399
1410
  if (nonParentExports.length > 0) {
1400
1411
  context.report({
1401
1412
  loc: { line: 1, column: 0 },
1402
- message: `index.ts must not re-export exclusive children: ${nonParentExports.join(", ")}. Only "${matchingTsx}" may be re-exported. See docs/code-organization-guide/rules/folder-nesting-rule.md`
1413
+ message: `index.ts must not re-export exclusive children: ${nonParentExports.join(", ")}. Only "${parentName}" may be re-exported. See docs/code-organization-guide/rules/folder-nesting-rule.md`
1403
1414
  });
1404
1415
  }
1405
1416
  }
@@ -1408,6 +1419,7 @@ var enforceBarrelExportsRule = {
1408
1419
  };
1409
1420
 
1410
1421
  // eslint/rules/component-placement.ts
1422
+ import fs2 from "fs";
1411
1423
  import path11 from "path";
1412
1424
 
1413
1425
  // eslint/project/ccf.ts
@@ -1506,6 +1518,13 @@ var REASON_TEXT = {
1506
1518
  "across-layers": "its consumers span more than one layer, so no feature can own it"
1507
1519
  };
1508
1520
  var sameFolder = (left, right) => left.length === right.length && left.every((segment, depth) => segment === right[depth]);
1521
+ function isNestedInside(expectedFolder, currentFolder, componentFile) {
1522
+ if (currentFolder.length !== expectedFolder.length + 1) return false;
1523
+ if (!sameFolder(currentFolder.slice(0, -1), expectedFolder)) return false;
1524
+ const folderName = currentFolder[currentFolder.length - 1];
1525
+ if (!folderName) return false;
1526
+ return fs2.existsSync(path11.join(path11.dirname(componentFile), `${folderName}.tsx`));
1527
+ }
1509
1528
  var componentPlacementRule = {
1510
1529
  meta: {
1511
1530
  schema: [],
@@ -1541,6 +1560,7 @@ var componentPlacementRule = {
1541
1560
  return;
1542
1561
  }
1543
1562
  if (sameFolder(currentFolder, placement.expectedFolder)) return;
1563
+ if (isNestedInside(placement.expectedFolder, currentFolder, componentFile)) return;
1544
1564
  const explanation = REASON_TEXT[placement.reason] ?? "that is where its consumers place it";
1545
1565
  context.report({
1546
1566
  node,
@@ -1597,7 +1617,7 @@ var supportFilePlacementRule = {
1597
1617
  };
1598
1618
 
1599
1619
  // eslint/rules/application-structure.ts
1600
- import fs2 from "fs";
1620
+ import fs3 from "fs";
1601
1621
  import path13 from "path";
1602
1622
  var MODULE_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
1603
1623
  var ROUTING_FILES = /* @__PURE__ */ new Set([
@@ -1672,10 +1692,10 @@ function componentFolderViolation(segments, sourceRoot) {
1672
1692
  if (!folder || SUPPORT_FOLDERS2.has(folder)) continue;
1673
1693
  const folderPath = path13.join(sourceRoot, ...segments.slice(0, depth + 1));
1674
1694
  const label = `src/${segments.slice(0, depth + 1).join("/")}/`;
1675
- if (!fs2.existsSync(path13.join(folderPath, `${folder}.tsx`))) {
1695
+ if (!fs3.existsSync(path13.join(folderPath, `${folder}.tsx`))) {
1676
1696
  return `A folder that is not a support folder must be a component folder; add "${folder}.tsx" to ${label} or move its files into a support folder.`;
1677
1697
  }
1678
- if (!fs2.existsSync(path13.join(folderPath, "index.ts"))) {
1698
+ if (!fs3.existsSync(path13.join(folderPath, "index.ts"))) {
1679
1699
  return `A component folder must have an index.ts that named-re-exports its component; add index.ts to ${label}.`;
1680
1700
  }
1681
1701
  }
@@ -1721,7 +1741,7 @@ var applicationStructureRule = {
1721
1741
  );
1722
1742
  }
1723
1743
  const moduleRoot = configModuleRoot(filename, sourceRoot);
1724
- if (moduleRoot && !fs2.existsSync(path13.join(moduleRoot, "index.ts"))) {
1744
+ if (moduleRoot && !fs3.existsSync(path13.join(moduleRoot, "index.ts"))) {
1725
1745
  return report2(
1726
1746
  context,
1727
1747
  `Add src/config/${path13.basename(moduleRoot)}/index.ts as the configuration module entry point.`
@@ -1842,16 +1862,25 @@ var namedExportsRule = {
1842
1862
  // eslint/rules/data-testid-case.ts
1843
1863
  import path15 from "path";
1844
1864
  var NEXT_ROUTING_FILES2 = /* @__PURE__ */ new Set([
1845
- "page",
1865
+ "default",
1866
+ "error",
1867
+ "global-error",
1868
+ "instrumentation",
1846
1869
  "layout",
1847
1870
  "loading",
1848
- "error",
1871
+ "middleware",
1849
1872
  "not-found",
1873
+ "page",
1850
1874
  "route",
1851
1875
  "template",
1852
- "default",
1853
- "middleware",
1854
- "instrumentation"
1876
+ // File conventions Next.js requires to keep their exact names in src/app/
1877
+ "apple-icon",
1878
+ "icon",
1879
+ "manifest",
1880
+ "opengraph-image",
1881
+ "robots",
1882
+ "sitemap",
1883
+ "twitter-image"
1855
1884
  ]);
1856
1885
  var isPascalCase5 = (value) => /^[A-Z][A-Za-z0-9]*$/.test(value);
1857
1886
  var isKebabCase3 = (value) => /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(value);
@@ -1907,7 +1936,7 @@ function toKebabCase(value) {
1907
1936
  }
1908
1937
 
1909
1938
  // eslint/rules/support-folder-shape.ts
1910
- import fs3 from "fs";
1939
+ import fs4 from "fs";
1911
1940
  import path16 from "path";
1912
1941
  var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
1913
1942
  var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
@@ -1928,7 +1957,7 @@ var supportFolderShapeRule = {
1928
1957
  const directory = path16.dirname(filename);
1929
1958
  let entries;
1930
1959
  try {
1931
- entries = fs3.readdirSync(directory);
1960
+ entries = fs4.readdirSync(directory);
1932
1961
  } catch {
1933
1962
  return {};
1934
1963
  }
@@ -3776,7 +3805,7 @@ var sourceUnderSrcRule = {
3776
3805
  };
3777
3806
 
3778
3807
  // eslint/rules/zirka-baseline.ts
3779
- import fs4 from "fs";
3808
+ import fs5 from "fs";
3780
3809
  import path36 from "path";
3781
3810
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
3782
3811
  var PRETTIER_CONFIGS = [
@@ -3815,12 +3844,12 @@ var zirkaBaselineRule = {
3815
3844
  );
3816
3845
  }
3817
3846
  const tsconfigPath = path36.join(projectRoot, "tsconfig.json");
3818
- if (!fs4.existsSync(tsconfigPath)) {
3847
+ if (!fs5.existsSync(tsconfigPath)) {
3819
3848
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
3820
3849
  } else {
3821
3850
  let extendsValue;
3822
3851
  try {
3823
- const parsed = JSON.parse(fs4.readFileSync(tsconfigPath, "utf8"));
3852
+ const parsed = JSON.parse(fs5.readFileSync(tsconfigPath, "utf8"));
3824
3853
  extendsValue = typeof parsed === "object" && parsed !== null && "extends" in parsed ? parsed.extends : void 0;
3825
3854
  } catch {
3826
3855
  report3(
@@ -3832,13 +3861,13 @@ var zirkaBaselineRule = {
3832
3861
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
3833
3862
  }
3834
3863
  }
3835
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs4.existsSync(path36.join(projectRoot, name)));
3864
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs5.existsSync(path36.join(projectRoot, name)));
3836
3865
  if (!prettierConfigFile) {
3837
3866
  report3(
3838
3867
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
3839
3868
  );
3840
3869
  } else {
3841
- const content = fs4.readFileSync(path36.join(projectRoot, prettierConfigFile), "utf8");
3870
+ const content = fs5.readFileSync(path36.join(projectRoot, prettierConfigFile), "utf8");
3842
3871
  if (!content.includes("zirka")) {
3843
3872
  report3(
3844
3873
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",