pasika 0.10.82 → 0.10.84

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.
@@ -237,6 +237,7 @@ declare const pasikaPlugin: {
237
237
  };
238
238
  };
239
239
  create(context: eslint.Rule.RuleContext): {
240
+ CallExpression(node: ESTree.CallExpression): void;
240
241
  JSXAttribute(node: JsxAttributeNode): void;
241
242
  };
242
243
  };
@@ -1218,6 +1218,8 @@ function isNestedInside(expectedFolder, currentFolder, componentFile) {
1218
1218
  if (!sameFolder(currentFolder.slice(0, -1), expectedFolder)) return false;
1219
1219
  const folderName = currentFolder[currentFolder.length - 1];
1220
1220
  if (!folderName) return false;
1221
+ const componentName = path10.basename(componentFile, path10.extname(componentFile));
1222
+ if (componentName !== folderName) return false;
1221
1223
  return fs3.existsSync(path10.join(path10.dirname(componentFile), `${folderName}.tsx`));
1222
1224
  }
1223
1225
  var componentPlacementRule = {
@@ -2937,7 +2939,13 @@ function parentComponentName(dirPath, folderName) {
2937
2939
  if (!fs4.existsSync(componentFile)) return void 0;
2938
2940
  try {
2939
2941
  const exports = parseModule(componentFile).exports;
2940
- return exports.find((moduleExport) => moduleExport.kind === "component")?.name;
2942
+ const classifiedComponent = exports.find((moduleExport) => moduleExport.kind === "component")?.name;
2943
+ if (classifiedComponent) return classifiedComponent;
2944
+ const normalizedFolderName = folderName.replaceAll("-", "").toLowerCase();
2945
+ const ownerExport = exports.find(
2946
+ (moduleExport) => isPascalCase4(moduleExport.name) && moduleExport.name.toLowerCase() === normalizedFolderName
2947
+ );
2948
+ return ownerExport?.name;
2941
2949
  } catch {
2942
2950
  return void 0;
2943
2951
  }
@@ -2987,7 +2995,7 @@ var enforceBarrelExportsRule = {
2987
2995
  if (nonParentExports.length > 0) {
2988
2996
  context.report({
2989
2997
  loc: { line: 1, column: 0 },
2990
- message: `index.ts must not re-export exclusive children: ${nonParentExports.join(", ")}. Only "${parentName}" may be re-exported. See docs/next-codebase-guide/rules/folder-nesting-rule.md`
2998
+ message: `index.ts must not re-export nested internals: ${nonParentExports.join(", ")}. Only "${parentName}" may be re-exported. See docs/next-codebase-guide/rules/folder-nesting-rule.md`
2991
2999
  });
2992
3000
  }
2993
3001
  }
@@ -3021,6 +3029,31 @@ function stringArguments(node) {
3021
3029
  }
3022
3030
  return [];
3023
3031
  }
3032
+ function staticClassLiterals(node) {
3033
+ if (!node) return [];
3034
+ if (node.type === "Literal" && typeof node.value === "string") return [node];
3035
+ if (node.type === "CallExpression") {
3036
+ if (node.callee.type === "Identifier" && node.callee.name === "cn") return [];
3037
+ return node.arguments.flatMap(
3038
+ (argument) => argument.type === "SpreadElement" ? [] : staticClassLiterals(argument)
3039
+ );
3040
+ }
3041
+ if (node.type === "ObjectExpression") {
3042
+ return node.properties.flatMap(
3043
+ (property) => property.type === "Property" ? staticClassLiterals(property.value) : []
3044
+ );
3045
+ }
3046
+ if (node.type === "ArrayExpression") {
3047
+ return node.elements.flatMap((element) => element?.type === "SpreadElement" ? [] : staticClassLiterals(element));
3048
+ }
3049
+ if (node.type === "ConditionalExpression") {
3050
+ return [...staticClassLiterals(node.consequent), ...staticClassLiterals(node.alternate)];
3051
+ }
3052
+ if (node.type === "LogicalExpression") {
3053
+ return [...staticClassLiterals(node.left), ...staticClassLiterals(node.right)];
3054
+ }
3055
+ return [];
3056
+ }
3024
3057
  var enforceCnMergeRule = {
3025
3058
  meta: { schema: [], type: "problem", docs: { description: "Enforce cn() for conditional class merging." } },
3026
3059
  create(context) {
@@ -3034,6 +3067,32 @@ var enforceCnMergeRule = {
3034
3067
  }
3035
3068
  }
3036
3069
  return {
3070
+ CallExpression(node) {
3071
+ if (node.callee.type !== "Identifier") return;
3072
+ if (node.callee.name === "cn") {
3073
+ for (const argument of node.arguments) {
3074
+ if (argument.type !== "Literal" || typeof argument.value !== "string" || classCount(argument.value) <= 5) {
3075
+ continue;
3076
+ }
3077
+ context.report({
3078
+ node: argument,
3079
+ message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/next-tailwind-guide/rules/class-composition-rule.md"
3080
+ });
3081
+ }
3082
+ return;
3083
+ }
3084
+ if (node.callee.name !== "cva") return;
3085
+ for (const argument of node.arguments) {
3086
+ if (argument.type === "SpreadElement") continue;
3087
+ for (const literal of staticClassLiterals(argument)) {
3088
+ if (typeof literal.value !== "string" || classCount(literal.value) <= 5) continue;
3089
+ context.report({
3090
+ node: literal,
3091
+ message: "Static cva class list with more than 5 classes must use cn() with grouped string literals. See docs/next-tailwind-guide/rules/class-composition-rule.md"
3092
+ });
3093
+ }
3094
+ }
3095
+ },
3037
3096
  JSXAttribute(node) {
3038
3097
  const attributeName = node.name?.name ?? "";
3039
3098
  const element = node.parent.parent;
@@ -3099,17 +3158,6 @@ var enforceCnMergeRule = {
3099
3158
  node,
3100
3159
  message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/next-tailwind-guide/rules/class-composition-rule.md"
3101
3160
  });
3102
- return;
3103
- }
3104
- if (expr.type === "CallExpression" && expr.callee.type === "Identifier" && expr.callee.name === "cn") {
3105
- for (const arg of expr.arguments) {
3106
- if (arg.type === "Literal" && typeof arg.value === "string" && classCount(arg.value) > 5) {
3107
- context.report({
3108
- node: arg,
3109
- message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/next-tailwind-guide/rules/class-composition-rule.md"
3110
- });
3111
- }
3112
- }
3113
3161
  }
3114
3162
  }
3115
3163
  };
@@ -3812,6 +3860,24 @@ function sourceSegments(sourceRoot, absolutePath) {
3812
3860
  }
3813
3861
  return relativePath.split(path31.sep);
3814
3862
  }
3863
+ function isWithin(root, candidate) {
3864
+ const relativePath = path31.relative(root, candidate);
3865
+ return relativePath === "" || !relativePath.startsWith("..") && !path31.isAbsolute(relativePath);
3866
+ }
3867
+ function componentFolderAncestors(targetFile, sourceRoot) {
3868
+ const folders = [];
3869
+ let current = path31.dirname(targetFile);
3870
+ while (current !== sourceRoot && isWithin(sourceRoot, current)) {
3871
+ const folderName = path31.basename(current);
3872
+ if (hasComponentOwner(current, folderName) && hasExactEntry(current, "index.ts")) {
3873
+ folders.push(current);
3874
+ }
3875
+ const parent = path31.dirname(current);
3876
+ if (parent === current) break;
3877
+ current = parent;
3878
+ }
3879
+ return folders;
3880
+ }
3815
3881
  function relativeSpecifier(filename, resolvedPath) {
3816
3882
  const relativePath = path31.relative(path31.dirname(filename), resolvedPath).split(path31.sep).join("/");
3817
3883
  return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
@@ -3841,6 +3907,26 @@ var importBoundariesRule = {
3841
3907
  return;
3842
3908
  }
3843
3909
  const importPath = source.value;
3910
+ const resolvedModule = resolveSpecifier(filename, importPath, sourceRoot);
3911
+ if (resolvedModule) {
3912
+ for (const componentFolder of componentFolderAncestors(resolvedModule, sourceRoot)) {
3913
+ if (isWithin(componentFolder, filename)) continue;
3914
+ const componentEntry = path31.join(componentFolder, "index.ts");
3915
+ if (path31.resolve(resolvedModule) === path31.resolve(componentEntry)) continue;
3916
+ const entrySpecifier = prefersRelative(filename, componentFolder) ? relativeSpecifier(filename, componentFolder) : aliasSpecifier(sourceRoot, componentFolder);
3917
+ const folderLabel = `src/${path31.relative(sourceRoot, componentFolder).split(path31.sep).join("/")}/`;
3918
+ const message = [
3919
+ `Do not import "${importPath}" across the ${folderLabel} component boundary;`,
3920
+ `outside consumers may import only "${entrySpecifier}".`,
3921
+ "Move nested internals to their CCF when they need reuse."
3922
+ ].join(" ");
3923
+ context.report({
3924
+ node: source,
3925
+ message
3926
+ });
3927
+ return;
3928
+ }
3929
+ }
3844
3930
  const resolvedPath = resolveSourceImport(sourceRoot, filename, importPath);
3845
3931
  if (!resolvedPath) {
3846
3932
  return;
@@ -5055,7 +5141,7 @@ var ownershipIndexCache = /* @__PURE__ */ new WeakMap();
5055
5141
  function normalizePath(value) {
5056
5142
  return value.replaceAll("\\", "/").toLowerCase();
5057
5143
  }
5058
- function isWithin(root, file) {
5144
+ function isWithin2(root, file) {
5059
5145
  const relative = path39.relative(root, file);
5060
5146
  return relative === "" || !relative.startsWith("..") && !path39.isAbsolute(relative);
5061
5147
  }
@@ -5197,7 +5283,7 @@ var ContractOwnershipIndex = class {
5197
5283
  const normalized = normalizePath(fileName);
5198
5284
  if (/\/typescript\/lib\/lib\.[^/]+\.d\.ts$/u.test(normalized)) return "platform";
5199
5285
  if (normalized.includes("/node_modules/")) return "third-party";
5200
- if (isWithin(this.cwd, path39.resolve(fileName))) return "first-party";
5286
+ if (isWithin2(this.cwd, path39.resolve(fileName))) return "first-party";
5201
5287
  return "unknown";
5202
5288
  }
5203
5289
  schemaOwnership(declaration) {
@@ -5211,7 +5297,7 @@ var ContractOwnershipIndex = class {
5211
5297
  }
5212
5298
  indexApiContracts() {
5213
5299
  for (const sourceFile of this.program.getSourceFiles()) {
5214
- if (sourceFile.isDeclarationFile || !isWithin(this.cwd, path39.resolve(sourceFile.fileName))) continue;
5300
+ if (sourceFile.isDeclarationFile || !isWithin2(this.cwd, path39.resolve(sourceFile.fileName))) continue;
5215
5301
  const visit = (node) => {
5216
5302
  if (ts7.isCallExpression(node) && this.isDefineApiContractCall(node)) this.indexApiContractCall(node);
5217
5303
  ts7.forEachChild(node, visit);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.10.82",
3
+ "version": "0.10.84",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",