pasika 0.8.1 → 0.9.0

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.
@@ -200,6 +200,7 @@ declare const pasikaPlugin: {
200
200
  "config-extraction": eslint.Rule.RuleModule;
201
201
  "value-extraction": eslint.Rule.RuleModule;
202
202
  "constant-casing": eslint.Rule.RuleModule;
203
+ "prefer-enum": eslint.Rule.RuleModule;
203
204
  "type-extraction": eslint.Rule.RuleModule;
204
205
  "zod-schema-validation": eslint.Rule.RuleModule;
205
206
  "schema-casing": eslint.Rule.RuleModule;
@@ -2170,8 +2170,47 @@ var constantCasingRule = {
2170
2170
  }
2171
2171
  };
2172
2172
 
2173
- // eslint/rules/import-through-index.ts
2173
+ // eslint/rules/prefer-enum.ts
2174
2174
  import path18 from "path";
2175
+ function isConstAssertion(node) {
2176
+ const typeAnnotation = node.typeAnnotation;
2177
+ return typeAnnotation?.type === "TSTypeReference" && typeAnnotation.typeName?.type === "Identifier" && typeAnnotation.typeName.name === "const";
2178
+ }
2179
+ function isEnumConvertibleProperty(property) {
2180
+ if (property.type !== "Property" || property.computed) return false;
2181
+ const { value } = property;
2182
+ return value.type === "Literal" && (typeof value.value === "string" || typeof value.value === "number");
2183
+ }
2184
+ var preferEnumRule = {
2185
+ meta: {
2186
+ schema: [],
2187
+ type: "problem",
2188
+ docs: {
2189
+ description: "Require a fixed set of named string/number values to be a TypeScript enum, not an `as const` object literal."
2190
+ }
2191
+ },
2192
+ create(context) {
2193
+ const filename = path18.resolve(context.filename);
2194
+ const sourceRoot = sourceRootOf(context);
2195
+ if (!filename.startsWith(sourceRoot + path18.sep)) return {};
2196
+ return {
2197
+ TSAsExpression(node) {
2198
+ if (!isConstAssertion(node)) return;
2199
+ const expression = node.expression;
2200
+ if (!expression || expression.type !== "ObjectExpression") return;
2201
+ if (expression.properties.length === 0) return;
2202
+ if (!expression.properties.every(isEnumConvertibleProperty)) return;
2203
+ context.report({
2204
+ node,
2205
+ message: "A fixed set of named values must be a TypeScript enum, not an object literal marked as const. See docs/next-codebase-guide/rules/constants-rule.md"
2206
+ });
2207
+ }
2208
+ };
2209
+ }
2210
+ };
2211
+
2212
+ // eslint/rules/import-through-index.ts
2213
+ import path19 from "path";
2175
2214
  var importThroughIndexRule = {
2176
2215
  meta: {
2177
2216
  schema: [],
@@ -2181,7 +2220,7 @@ var importThroughIndexRule = {
2181
2220
  }
2182
2221
  },
2183
2222
  create(context) {
2184
- const filename = path18.resolve(context.filename);
2223
+ const filename = path19.resolve(context.filename);
2185
2224
  const sourceRoot = sourceRootOf2(context, filename);
2186
2225
  return {
2187
2226
  Program(node) {
@@ -2193,7 +2232,7 @@ var importThroughIndexRule = {
2193
2232
  (segment) => ["constants", "types", "schemas"].includes(segment)
2194
2233
  );
2195
2234
  const supportFolder = supportFolderIndex >= 0 ? targetSegments[supportFolderIndex] : void 0;
2196
- if (!supportFolder || path18.basename(target).startsWith("index.")) continue;
2235
+ if (!supportFolder || path19.basename(target).startsWith("index.")) continue;
2197
2236
  const folderIndex = targetSegments.slice(0, supportFolderIndex + 1);
2198
2237
  const expected = `@/${folderIndex.join("/")}`;
2199
2238
  context.report({
@@ -2215,14 +2254,14 @@ function importSpecifiers(source) {
2215
2254
  return specifiers;
2216
2255
  }
2217
2256
  function sourceRootOf2(context, filename) {
2218
- const marker = `${path18.sep}src${path18.sep}`;
2257
+ const marker = `${path19.sep}src${path19.sep}`;
2219
2258
  const srcIndex = filename.lastIndexOf(marker);
2220
2259
  if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
2221
- return path18.resolve(context.cwd ?? process.cwd(), "src");
2260
+ return path19.resolve(context.cwd ?? process.cwd(), "src");
2222
2261
  }
2223
2262
 
2224
2263
  // eslint/rules/util-file-name.ts
2225
- import path19 from "path";
2264
+ import path20 from "path";
2226
2265
  function toKebabCase2(value) {
2227
2266
  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();
2228
2267
  }
@@ -2235,7 +2274,7 @@ var utilFileNameRule = {
2235
2274
  }
2236
2275
  },
2237
2276
  create(context) {
2238
- const filename = path19.resolve(context.filename);
2277
+ const filename = path20.resolve(context.filename);
2239
2278
  const segments = filename.replace(/\\/g, "/").split("/");
2240
2279
  if (!segments.includes("utils")) return {};
2241
2280
  let module;
@@ -2249,13 +2288,13 @@ var utilFileNameRule = {
2249
2288
  const functionName = functions[0]?.name;
2250
2289
  if (!functionName) return {};
2251
2290
  const expected = toKebabCase2(functionName);
2252
- const actual = path19.basename(filename, path19.extname(filename));
2291
+ const actual = path20.basename(filename, path20.extname(filename));
2253
2292
  if (!expected || actual === expected) return {};
2254
2293
  return {
2255
2294
  Program(node) {
2256
2295
  context.report({
2257
2296
  node,
2258
- message: `A utility file exporting ${functionName} must be named ${expected}.${path19.extname(filename).slice(1)}.`
2297
+ message: `A utility file exporting ${functionName} must be named ${expected}.${path20.extname(filename).slice(1)}.`
2259
2298
  });
2260
2299
  }
2261
2300
  };
@@ -2263,7 +2302,7 @@ var utilFileNameRule = {
2263
2302
  };
2264
2303
 
2265
2304
  // eslint/rules/no-util-barrel.ts
2266
- import path20 from "path";
2305
+ import path21 from "path";
2267
2306
  var noUtilBarrelRule = {
2268
2307
  meta: {
2269
2308
  schema: [],
@@ -2273,7 +2312,7 @@ var noUtilBarrelRule = {
2273
2312
  }
2274
2313
  },
2275
2314
  create(context) {
2276
- const filename = path20.resolve(context.filename);
2315
+ const filename = path21.resolve(context.filename);
2277
2316
  const sourceRoot = sourceRootOf3(context, filename);
2278
2317
  return {
2279
2318
  Program(node) {
@@ -2282,7 +2321,7 @@ var noUtilBarrelRule = {
2282
2321
  if (!target) continue;
2283
2322
  const segments = target.replace(/\\/g, "/").split("/");
2284
2323
  const utilsIndex = segments.lastIndexOf("utils");
2285
- if (utilsIndex < 0 || !path20.basename(target).startsWith("index.")) continue;
2324
+ if (utilsIndex < 0 || !path21.basename(target).startsWith("index.")) continue;
2286
2325
  context.report({
2287
2326
  node,
2288
2327
  message: `Import utilities directly instead of through "${specifier}". See docs/next-codebase-guide/rules/utilities-rule.md`
@@ -2302,10 +2341,10 @@ function importSpecifiers2(source) {
2302
2341
  return specifiers;
2303
2342
  }
2304
2343
  function sourceRootOf3(context, filename) {
2305
- const marker = `${path20.sep}src${path20.sep}`;
2344
+ const marker = `${path21.sep}src${path21.sep}`;
2306
2345
  const srcIndex = filename.lastIndexOf(marker);
2307
2346
  if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
2308
- return path20.resolve(context.cwd ?? process.cwd(), "src");
2347
+ return path21.resolve(context.cwd ?? process.cwd(), "src");
2309
2348
  }
2310
2349
 
2311
2350
  // eslint/rules/jsx-hygiene.ts
@@ -2398,7 +2437,7 @@ var jsxHygieneRule = {
2398
2437
  };
2399
2438
 
2400
2439
  // eslint/rules/interactive-component.ts
2401
- import path21 from "path";
2440
+ import path22 from "path";
2402
2441
  var INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
2403
2442
  "a",
2404
2443
  "button",
@@ -2553,8 +2592,8 @@ var interactiveComponentRule = {
2553
2592
  },
2554
2593
  create(context) {
2555
2594
  if (!context.filename.endsWith(".tsx") && !context.filename.endsWith(".jsx")) return {};
2556
- const filename = path21.resolve(context.filename);
2557
- const base = path21.basename(filename, path21.extname(filename));
2595
+ const filename = path22.resolve(context.filename);
2596
+ const base = path22.basename(filename, path22.extname(filename));
2558
2597
  if (NEXT_ROUTING_FILES3.has(base)) return {};
2559
2598
  return {
2560
2599
  JSXElement(node) {
@@ -2805,12 +2844,12 @@ var cvaBooleanVariantsRule = {
2805
2844
  };
2806
2845
 
2807
2846
  // eslint/rules/cross-feature-import.ts
2808
- import path22 from "path";
2847
+ import path23 from "path";
2809
2848
  var FEATURES_SEGMENT = "features";
2810
2849
  function featureNameOf(resolvedPath, sourceRoot) {
2811
- const relative = path22.relative(sourceRoot, resolvedPath);
2850
+ const relative = path23.relative(sourceRoot, resolvedPath);
2812
2851
  if (relative.startsWith("..")) return void 0;
2813
- const segments = relative.split(path22.sep);
2852
+ const segments = relative.split(path23.sep);
2814
2853
  if (segments[0] !== FEATURES_SEGMENT || segments.length < 2) return void 0;
2815
2854
  return segments[1];
2816
2855
  }
@@ -2826,9 +2865,9 @@ var crossFeatureImportRule = {
2826
2865
  const filename = context.filename;
2827
2866
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
2828
2867
  const sourceRoot = sourceRootOf(context);
2829
- const fileRelative = path22.relative(sourceRoot, filename);
2868
+ const fileRelative = path23.relative(sourceRoot, filename);
2830
2869
  if (fileRelative.startsWith("..")) return {};
2831
- const fileSegments = fileRelative.split(path22.sep);
2870
+ const fileSegments = fileRelative.split(path23.sep);
2832
2871
  const isInCompositions = fileSegments[0] === "compositions";
2833
2872
  const isInApp = fileSegments[0] === "app";
2834
2873
  const isConfig = fileSegments[0] === "config";
@@ -2842,9 +2881,9 @@ var crossFeatureImportRule = {
2842
2881
  if (typeof source.value !== "string") return;
2843
2882
  let resolved;
2844
2883
  if (source.value.startsWith("@/")) {
2845
- resolved = path22.resolve(sourceRoot, source.value.slice(2));
2884
+ resolved = path23.resolve(sourceRoot, source.value.slice(2));
2846
2885
  } else if (source.value.startsWith(".")) {
2847
- resolved = path22.resolve(path22.dirname(filename), source.value);
2886
+ resolved = path23.resolve(path23.dirname(filename), source.value);
2848
2887
  }
2849
2888
  if (!resolved) return;
2850
2889
  const feature = featureNameOf(resolved, sourceRoot);
@@ -2863,7 +2902,7 @@ var crossFeatureImportRule = {
2863
2902
  };
2864
2903
 
2865
2904
  // eslint/rules/pure-function-extract.ts
2866
- import path23 from "path";
2905
+ import path24 from "path";
2867
2906
  function isComponentLikeName(name) {
2868
2907
  return /^[A-Z]/.test(name);
2869
2908
  }
@@ -2892,9 +2931,9 @@ var pureFunctionExtractRule = {
2892
2931
  const filename = context.filename;
2893
2932
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
2894
2933
  const sourceRoot = sourceRootOf(context);
2895
- const relative = path23.relative(sourceRoot, filename);
2934
+ const relative = path24.relative(sourceRoot, filename);
2896
2935
  if (relative.startsWith("..")) return {};
2897
- const segments = relative.split(path23.sep);
2936
+ const segments = relative.split(path24.sep);
2898
2937
  if (segments[0] === "utils") return {};
2899
2938
  if (segments[0] === "app") return {};
2900
2939
  const supportFolders = /* @__PURE__ */ new Set(["hooks", "types", "schemas", "constants", "utils"]);
@@ -2934,7 +2973,7 @@ var pureFunctionExtractRule = {
2934
2973
  };
2935
2974
 
2936
2975
  // eslint/rules/hook-complexity.ts
2937
- import path24 from "path";
2976
+ import path25 from "path";
2938
2977
  import ts4 from "typescript";
2939
2978
  var REACT_HOOKS = /* @__PURE__ */ new Set([
2940
2979
  "useState",
@@ -2987,9 +3026,9 @@ var hookComplexityRule = {
2987
3026
  create(context) {
2988
3027
  const filename = context.filename;
2989
3028
  const sourceRoot = sourceRootOf(context);
2990
- const relative = path24.relative(sourceRoot, filename);
3029
+ const relative = path25.relative(sourceRoot, filename);
2991
3030
  if (relative.startsWith("..")) return {};
2992
- const segments = relative.split(path24.sep);
3031
+ const segments = relative.split(path25.sep);
2993
3032
  const sourceText = context.sourceCode.text;
2994
3033
  function checkHook(node, name, body, exported) {
2995
3034
  if (!exported) return;
@@ -3031,9 +3070,9 @@ var hookComplexityRule = {
3031
3070
  };
3032
3071
 
3033
3072
  // eslint/rules/locale-dotted-path.ts
3034
- import path25 from "path";
3073
+ import path26 from "path";
3035
3074
  function isInLocalesDir(filename) {
3036
- const segments = path25.resolve(filename).split(path25.sep);
3075
+ const segments = path26.resolve(filename).split(path26.sep);
3037
3076
  const srcIdx = segments.lastIndexOf("src");
3038
3077
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
3039
3078
  }
@@ -3082,9 +3121,9 @@ var localeDottedPathRule = {
3082
3121
  };
3083
3122
 
3084
3123
  // eslint/rules/locales-location.ts
3085
- import path26 from "path";
3124
+ import path27 from "path";
3086
3125
  function isLocalesFile(filename) {
3087
- const segments = path26.resolve(filename).split(path26.sep);
3126
+ const segments = path27.resolve(filename).split(path27.sep);
3088
3127
  const srcIdx = segments.lastIndexOf("src");
3089
3128
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
3090
3129
  }
@@ -3109,7 +3148,7 @@ var localesLocationRule = {
3109
3148
  create(context) {
3110
3149
  if (isLocalesFile(context.filename) || isTestFile(context.filename)) return {};
3111
3150
  const filename = context.filename;
3112
- const segments = path26.resolve(filename).split(path26.sep);
3151
+ const segments = path27.resolve(filename).split(path27.sep);
3113
3152
  const srcIdx = segments.lastIndexOf("src");
3114
3153
  if (srcIdx === -1) return {};
3115
3154
  const folder = segments[srcIdx + 1];
@@ -3133,7 +3172,7 @@ var localesLocationRule = {
3133
3172
  };
3134
3173
 
3135
3174
  // eslint/rules/hook-extraction.ts
3136
- import path27 from "path";
3175
+ import path28 from "path";
3137
3176
  var hookExtractionRule = {
3138
3177
  meta: {
3139
3178
  schema: [],
@@ -3144,7 +3183,7 @@ var hookExtractionRule = {
3144
3183
  },
3145
3184
  create(context) {
3146
3185
  const sourceRoot = sourceRootOf(context);
3147
- const file = path27.resolve(context.filename);
3186
+ const file = path28.resolve(context.filename);
3148
3187
  const segments = segmentsOf(file, sourceRoot);
3149
3188
  if (segments.length === 0) return {};
3150
3189
  const index = getProjectIndex(sourceRoot);
@@ -3170,7 +3209,7 @@ var hookExtractionRule = {
3170
3209
  };
3171
3210
 
3172
3211
  // eslint/rules/value-extraction.ts
3173
- import path28 from "path";
3212
+ import path29 from "path";
3174
3213
  var valueExtractionRule = {
3175
3214
  meta: {
3176
3215
  schema: [],
@@ -3181,7 +3220,7 @@ var valueExtractionRule = {
3181
3220
  },
3182
3221
  create(context) {
3183
3222
  const sourceRoot = sourceRootOf(context);
3184
- const file = path28.resolve(context.filename);
3223
+ const file = path29.resolve(context.filename);
3185
3224
  const segments = segmentsOf(file, sourceRoot);
3186
3225
  if (segments.length === 0 || segments[0] !== "app") return {};
3187
3226
  const index = getProjectIndex(sourceRoot);
@@ -3202,7 +3241,7 @@ var valueExtractionRule = {
3202
3241
  };
3203
3242
 
3204
3243
  // eslint/rules/config-extraction.ts
3205
- import path29 from "path";
3244
+ import path30 from "path";
3206
3245
  var configExtractionRule = {
3207
3246
  meta: {
3208
3247
  schema: [],
@@ -3213,7 +3252,7 @@ var configExtractionRule = {
3213
3252
  },
3214
3253
  create(context) {
3215
3254
  const sourceRoot = sourceRootOf(context);
3216
- const file = path29.resolve(context.filename);
3255
+ const file = path30.resolve(context.filename);
3217
3256
  const segments = segmentsOf(file, sourceRoot);
3218
3257
  if (segments.length < 3 || segments[0] !== "config") return {};
3219
3258
  if (SUPPORT_FOLDERS2.has(segments[2] ?? "")) return {};
@@ -3251,7 +3290,7 @@ var configExtractionRule = {
3251
3290
  };
3252
3291
 
3253
3292
  // eslint/rules/component-nesting.ts
3254
- import path30 from "path";
3293
+ import path31 from "path";
3255
3294
  var componentNestingRule = {
3256
3295
  meta: {
3257
3296
  schema: [],
@@ -3262,7 +3301,7 @@ var componentNestingRule = {
3262
3301
  },
3263
3302
  create(context) {
3264
3303
  const sourceRoot = sourceRootOf(context);
3265
- const file = path30.resolve(context.filename);
3304
+ const file = path31.resolve(context.filename);
3266
3305
  const segments = segmentsOf(file, sourceRoot);
3267
3306
  if (segments.length !== 4 || segments[0] !== "features") return {};
3268
3307
  const index = getProjectIndex(sourceRoot);
@@ -3295,7 +3334,7 @@ var componentNestingRule = {
3295
3334
  };
3296
3335
 
3297
3336
  // eslint/rules/stay-flat.ts
3298
- import path31 from "path";
3337
+ import path32 from "path";
3299
3338
  var stayFlatRule = {
3300
3339
  meta: {
3301
3340
  schema: [],
@@ -3306,7 +3345,7 @@ var stayFlatRule = {
3306
3345
  },
3307
3346
  create(context) {
3308
3347
  const sourceRoot = sourceRootOf(context);
3309
- const file = path31.resolve(context.filename);
3348
+ const file = path32.resolve(context.filename);
3310
3349
  const segments = segmentsOf(file, sourceRoot);
3311
3350
  if (segments.length !== 3 || segments[0] !== "features") return {};
3312
3351
  const index = getProjectIndex(sourceRoot);
@@ -3346,7 +3385,7 @@ var stayFlatRule = {
3346
3385
  };
3347
3386
 
3348
3387
  // eslint/rules/type-extraction.ts
3349
- import path32 from "path";
3388
+ import path33 from "path";
3350
3389
  var typeExtractionRule = {
3351
3390
  meta: {
3352
3391
  schema: [],
@@ -3357,7 +3396,7 @@ var typeExtractionRule = {
3357
3396
  },
3358
3397
  create(context) {
3359
3398
  const sourceRoot = sourceRootOf(context);
3360
- const file = path32.resolve(context.filename);
3399
+ const file = path33.resolve(context.filename);
3361
3400
  const segments = segmentsOf(file, sourceRoot);
3362
3401
  if (segments.length === 0) return {};
3363
3402
  const index = getProjectIndex(sourceRoot);
@@ -3403,7 +3442,7 @@ var typeExtractionRule = {
3403
3442
  };
3404
3443
 
3405
3444
  // eslint/rules/locale-placement.ts
3406
- import path33 from "path";
3445
+ import path34 from "path";
3407
3446
  import { readFileSync as readFileSync4 } from "fs";
3408
3447
  import ts5 from "typescript";
3409
3448
  var LOCALE_ACCESS = /\blocales\.(?<key>[A-Za-z_$][\w$]*)/g;
@@ -3451,7 +3490,7 @@ var localePlacementRule = {
3451
3490
  },
3452
3491
  create(context) {
3453
3492
  const sourceRoot = sourceRootOf(context);
3454
- const file = path33.resolve(context.filename);
3493
+ const file = path34.resolve(context.filename);
3455
3494
  const segments = segmentsOf(file, sourceRoot);
3456
3495
  if (segments.length === 0) return {};
3457
3496
  const index = getProjectIndex(sourceRoot);
@@ -3529,7 +3568,7 @@ var localePlacementRule = {
3529
3568
  };
3530
3569
 
3531
3570
  // eslint/rules/sole-state-owner.ts
3532
- import path34 from "path";
3571
+ import path35 from "path";
3533
3572
  import ts6 from "typescript";
3534
3573
  function findStateHooks(node) {
3535
3574
  const hooks = [];
@@ -3609,7 +3648,7 @@ var soleStateOwnerRule = {
3609
3648
  }
3610
3649
  },
3611
3650
  create(context) {
3612
- const filename = path34.resolve(context.filename);
3651
+ const filename = path35.resolve(context.filename);
3613
3652
  if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
3614
3653
  const text = context.sourceCode.text;
3615
3654
  const components = parseComponentInfo(text, filename);
@@ -3688,7 +3727,7 @@ function usesOutsideJsx(declaration, hook, children) {
3688
3727
  }
3689
3728
 
3690
3729
  // eslint/rules/locale-key-shape.ts
3691
- import path35 from "path";
3730
+ import path36 from "path";
3692
3731
  var MAX_KEY_LENGTH = 30;
3693
3732
  var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
3694
3733
  "Button",
@@ -3738,7 +3777,7 @@ var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
3738
3777
  var CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
3739
3778
  var ENGLISH = /^[A-Za-z0-9_]*$/;
3740
3779
  function isLocalesFile2(filename) {
3741
- const segments = path35.resolve(filename).split(path35.sep);
3780
+ const segments = path36.resolve(filename).split(path36.sep);
3742
3781
  const srcIdx = segments.lastIndexOf("src");
3743
3782
  return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
3744
3783
  }
@@ -3809,7 +3848,7 @@ var localeKeyShapeRule = {
3809
3848
  };
3810
3849
 
3811
3850
  // eslint/rules/shared-style-dedup.ts
3812
- import path36 from "path";
3851
+ import path37 from "path";
3813
3852
  import { readFileSync as readFileSync5, statSync as statSync3 } from "fs";
3814
3853
  var CLASS_NAME = /className="(?<classes>[^"]+)"/g;
3815
3854
  var comboCache;
@@ -3847,7 +3886,7 @@ var sharedStyleDedupRule = {
3847
3886
  },
3848
3887
  create(context) {
3849
3888
  const sourceRoot = sourceRootOf(context);
3850
- const file = path36.resolve(context.filename);
3889
+ const file = path37.resolve(context.filename);
3851
3890
  const segments = segmentsOf(file, sourceRoot);
3852
3891
  if (segments.length === 0) return {};
3853
3892
  const index = getProjectIndex(sourceRoot);
@@ -4051,7 +4090,7 @@ var zodSchemaValidationRule = {
4051
4090
  };
4052
4091
 
4053
4092
  // eslint/rules/schema-casing.ts
4054
- import path37 from "path";
4093
+ import path38 from "path";
4055
4094
  function isCamelCase(name) {
4056
4095
  return /^[a-z][a-zA-Z0-9]*$/.test(name);
4057
4096
  }
@@ -4079,9 +4118,9 @@ var schemaCasingRule = {
4079
4118
  }
4080
4119
  },
4081
4120
  create(context) {
4082
- const filename = path37.resolve(context.filename);
4121
+ const filename = path38.resolve(context.filename);
4083
4122
  const sourceRoot = sourceRootOf(context);
4084
- if (!filename.startsWith(sourceRoot + path37.sep)) return {};
4123
+ if (!filename.startsWith(sourceRoot + path38.sep)) return {};
4085
4124
  let zodLocalName;
4086
4125
  return {
4087
4126
  ImportDeclaration(node) {
@@ -4113,7 +4152,7 @@ var schemaCasingRule = {
4113
4152
  };
4114
4153
 
4115
4154
  // eslint/rules/component-casing.ts
4116
- import path38 from "path";
4155
+ import path39 from "path";
4117
4156
  function isPascalCase6(name) {
4118
4157
  return /^[A-Z][A-Za-z0-9]*$/.test(name);
4119
4158
  }
@@ -4126,10 +4165,10 @@ var componentCasingRule = {
4126
4165
  }
4127
4166
  },
4128
4167
  create(context) {
4129
- const filename = path38.resolve(context.filename);
4168
+ const filename = path39.resolve(context.filename);
4130
4169
  const sourceRoot = sourceRootOf(context);
4131
- if (!filename.startsWith(sourceRoot + path38.sep)) return {};
4132
- if (path38.extname(filename) !== ".tsx") return {};
4170
+ if (!filename.startsWith(sourceRoot + path39.sep)) return {};
4171
+ if (path39.extname(filename) !== ".tsx") return {};
4133
4172
  return {
4134
4173
  Program(node) {
4135
4174
  for (const declaration of findJsxReturningDeclarations(context.sourceCode.text, filename)) {
@@ -4146,7 +4185,7 @@ var componentCasingRule = {
4146
4185
  };
4147
4186
 
4148
4187
  // eslint/rules/source-under-src.ts
4149
- import path39 from "path";
4188
+ import path40 from "path";
4150
4189
  var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
4151
4190
  ".agents",
4152
4191
  ".cache",
@@ -4187,14 +4226,14 @@ var sourceUnderSrcRule = {
4187
4226
  }
4188
4227
  },
4189
4228
  create(context) {
4190
- const filename = path39.resolve(context.filename);
4229
+ const filename = path40.resolve(context.filename);
4191
4230
  if (!MODULE_EXTENSION.test(filename)) return {};
4192
- const relative = path39.relative(context.cwd, filename).replace(/\\/g, "/");
4231
+ const relative = path40.relative(context.cwd, filename).replace(/\\/g, "/");
4193
4232
  if (relative === "src" || relative.startsWith("src/")) return {};
4194
4233
  const topLevel = relative.split("/")[0] ?? "";
4195
4234
  if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
4196
4235
  if (!relative.includes("/")) {
4197
- const basename = path39.basename(filename);
4236
+ const basename = path40.basename(filename);
4198
4237
  if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
4199
4238
  }
4200
4239
  return {
@@ -4211,7 +4250,7 @@ var sourceUnderSrcRule = {
4211
4250
 
4212
4251
  // eslint/rules/zirka-baseline.ts
4213
4252
  import fs5 from "fs";
4214
- import path40 from "path";
4253
+ import path41 from "path";
4215
4254
  var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
4216
4255
  var PRETTIER_CONFIGS = [
4217
4256
  "prettier.config.mjs",
@@ -4230,10 +4269,10 @@ var zirkaBaselineRule = {
4230
4269
  }
4231
4270
  },
4232
4271
  create(context) {
4233
- const filename = path40.resolve(context.filename);
4234
- const basename = path40.basename(filename);
4272
+ const filename = path41.resolve(context.filename);
4273
+ const basename = path41.basename(filename);
4235
4274
  if (!ESLINT_CONFIG.test(basename)) return {};
4236
- const projectRoot = path40.dirname(filename);
4275
+ const projectRoot = path41.dirname(filename);
4237
4276
  const report3 = (message) => {
4238
4277
  context.report({
4239
4278
  node: context.sourceCode.ast,
@@ -4248,7 +4287,7 @@ var zirkaBaselineRule = {
4248
4287
  'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
4249
4288
  );
4250
4289
  }
4251
- const tsconfigPath = path40.join(projectRoot, "tsconfig.json");
4290
+ const tsconfigPath = path41.join(projectRoot, "tsconfig.json");
4252
4291
  if (!fs5.existsSync(tsconfigPath)) {
4253
4292
  report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
4254
4293
  } else {
@@ -4266,13 +4305,13 @@ var zirkaBaselineRule = {
4266
4305
  report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
4267
4306
  }
4268
4307
  }
4269
- const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs5.existsSync(path40.join(projectRoot, name)));
4308
+ const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs5.existsSync(path41.join(projectRoot, name)));
4270
4309
  if (!prettierConfigFile) {
4271
4310
  report3(
4272
4311
  "No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
4273
4312
  );
4274
4313
  } else {
4275
- const content = fs5.readFileSync(path40.join(projectRoot, prettierConfigFile), "utf8");
4314
+ const content = fs5.readFileSync(path41.join(projectRoot, prettierConfigFile), "utf8");
4276
4315
  if (!content.includes("zirka")) {
4277
4316
  report3(
4278
4317
  "The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
@@ -4342,7 +4381,7 @@ var docKindSuffixRule = {
4342
4381
  };
4343
4382
 
4344
4383
  // eslint/rules/documentation/title-matches-file-name.ts
4345
- import path41 from "path";
4384
+ import path42 from "path";
4346
4385
  function toExpectedFileName(title) {
4347
4386
  return `${title.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}.md`;
4348
4387
  }
@@ -4362,7 +4401,7 @@ var titleMatchesFileNameRule = {
4362
4401
  if (!filename.endsWith(".md")) return;
4363
4402
  const title = getTextContent(node).trim();
4364
4403
  const expectedFileName = toExpectedFileName(title);
4365
- const actualFileName = path41.basename(filename);
4404
+ const actualFileName = path42.basename(filename);
4366
4405
  if (!title) {
4367
4406
  context.report({
4368
4407
  node,
@@ -4805,20 +4844,20 @@ var referenceBlockHeadingsRule = {
4805
4844
 
4806
4845
  // eslint/rules/documentation/support-document-placement.ts
4807
4846
  import { existsSync as existsSync2 } from "fs";
4808
- import path42 from "path";
4847
+ import path43 from "path";
4809
4848
  function checkPlacement(filename, kind) {
4810
- const parentFolder = path42.basename(path42.dirname(filename));
4849
+ const parentFolder = path43.basename(path43.dirname(filename));
4811
4850
  const expectedParent = `${kind}s`;
4812
4851
  if (parentFolder !== expectedParent) {
4813
4852
  return `${kind} lives in "${parentFolder}/" instead of "${expectedParent}/"`;
4814
4853
  }
4815
- const guideFolderPath = path42.dirname(path42.dirname(filename));
4816
- const guideFolder = path42.basename(guideFolderPath);
4854
+ const guideFolderPath = path43.dirname(path43.dirname(filename));
4855
+ const guideFolder = path43.basename(guideFolderPath);
4817
4856
  if (!guideFolder.endsWith("-guide")) {
4818
4857
  return `${kind} owner folder "${guideFolder}/" does not use the "*-guide/" suffix`;
4819
4858
  }
4820
4859
  const entryPoint = `${guideFolder}.md`;
4821
- if (!existsSync2(path42.join(guideFolderPath, entryPoint))) {
4860
+ if (!existsSync2(path43.join(guideFolderPath, entryPoint))) {
4822
4861
  return `${kind} owner folder "${guideFolder}/" has no "${entryPoint}" entry point`;
4823
4862
  }
4824
4863
  return void 0;
@@ -4877,11 +4916,11 @@ var noTemplatePromptRule = {
4877
4916
  };
4878
4917
 
4879
4918
  // eslint/rules/documentation/guide-folder-entry-point.ts
4880
- import path44 from "path";
4919
+ import path45 from "path";
4881
4920
 
4882
4921
  // eslint/rules/documentation/project-index.ts
4883
4922
  import { readdirSync as readdirSync3, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
4884
- import path43 from "path";
4923
+ import path44 from "path";
4885
4924
  var KIND_BY_SUFFIX = [
4886
4925
  ["-rule.md", "rule"],
4887
4926
  ["-guide.md", "guide"],
@@ -4890,7 +4929,7 @@ var KIND_BY_SUFFIX = [
4890
4929
  ];
4891
4930
  function listMarkdownFiles(dir) {
4892
4931
  return readdirSync3(dir).flatMap((entry) => {
4893
- const entryPath = path43.join(dir, entry);
4932
+ const entryPath = path44.join(dir, entry);
4894
4933
  if (statSync4(entryPath).isDirectory()) {
4895
4934
  return entry.startsWith("_") ? [] : listMarkdownFiles(entryPath);
4896
4935
  }
@@ -4908,11 +4947,11 @@ function getProjectDocs(docsRoot) {
4908
4947
  if (cached) return cached;
4909
4948
  const files = listMarkdownFiles(docsRoot);
4910
4949
  const docs = files.sort((a, b) => a.localeCompare(b)).map((filePath) => {
4911
- const fileName = path43.basename(filePath);
4950
+ const fileName = path44.basename(filePath);
4912
4951
  const kind = KIND_BY_SUFFIX.find(([suffix]) => fileName.endsWith(suffix))?.[1];
4913
4952
  return {
4914
4953
  filePath,
4915
- doc: path43.relative(docsRoot, filePath).split(path43.sep).join("/"),
4954
+ doc: path44.relative(docsRoot, filePath).split(path44.sep).join("/"),
4916
4955
  fileName,
4917
4956
  kind,
4918
4957
  title: extractTitle(filePath)
@@ -4922,12 +4961,12 @@ function getProjectDocs(docsRoot) {
4922
4961
  return docs;
4923
4962
  }
4924
4963
  function findDocsRoot(filePath) {
4925
- let dir = path43.dirname(filePath);
4964
+ let dir = path44.dirname(filePath);
4926
4965
  for (; ; ) {
4927
- if (path43.basename(dir) === "docs" && statSync4(dir).isDirectory()) {
4966
+ if (path44.basename(dir) === "docs" && statSync4(dir).isDirectory()) {
4928
4967
  return dir;
4929
4968
  }
4930
- const parent = path43.dirname(dir);
4969
+ const parent = path44.dirname(dir);
4931
4970
  if (parent === dir) return void 0;
4932
4971
  dir = parent;
4933
4972
  }
@@ -4951,13 +4990,13 @@ var guideFolderEntryPointRule = {
4951
4990
  if (!docsRoot) return;
4952
4991
  const docs = getProjectDocs(docsRoot);
4953
4992
  const guideFolders = new Set(
4954
- docs.filter((doc) => ["rules", "references"].includes(path44.basename(path44.dirname(doc.filePath)))).map((doc) => path44.dirname(path44.dirname(doc.filePath))).filter((folder) => path44.resolve(folder) !== path44.resolve(docsRoot))
4993
+ docs.filter((doc) => ["rules", "references"].includes(path45.basename(path45.dirname(doc.filePath)))).map((doc) => path45.dirname(path45.dirname(doc.filePath))).filter((folder) => path45.resolve(folder) !== path45.resolve(docsRoot))
4955
4994
  );
4956
- const currentDir = path44.dirname(filename);
4995
+ const currentDir = path45.dirname(filename);
4957
4996
  if (guideFolders.has(currentDir)) {
4958
- const expectedEntryPoint = `${path44.basename(currentDir)}.md`;
4997
+ const expectedEntryPoint = `${path45.basename(currentDir)}.md`;
4959
4998
  const hasEntryPoint = docs.some(
4960
- (doc) => doc.kind === "guide" && path44.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
4999
+ (doc) => doc.kind === "guide" && path45.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
4961
5000
  );
4962
5001
  if (!hasEntryPoint) {
4963
5002
  context.report({
@@ -5182,7 +5221,7 @@ var noNestedHowToRule = {
5182
5221
 
5183
5222
  // eslint/rules/documentation/glossary-term-linking.ts
5184
5223
  import { readFileSync as readFileSync7 } from "fs";
5185
- import path45 from "path";
5224
+ import path46 from "path";
5186
5225
  function extractGlossaryTerms(filePath) {
5187
5226
  const content = readFileSync7(filePath, "utf8");
5188
5227
  const terms = [];
@@ -5236,9 +5275,9 @@ var glossaryTermLinkingRule = {
5236
5275
  const docsRoot = findDocsRoot(filename);
5237
5276
  if (!docsRoot) return;
5238
5277
  const docs = getProjectDocs(docsRoot);
5239
- const guideDir = path45.dirname(filename);
5278
+ const guideDir = path46.dirname(filename);
5240
5279
  const guideReferences = docs.filter(
5241
- (doc) => doc.kind === "reference" && path45.dirname(doc.filePath) === guideDir
5280
+ (doc) => doc.kind === "reference" && path46.dirname(doc.filePath) === guideDir
5242
5281
  );
5243
5282
  if (guideReferences.length === 0) return;
5244
5283
  const glossaryTerms = [];
@@ -5263,7 +5302,7 @@ var glossaryTermLinkingRule = {
5263
5302
 
5264
5303
  // eslint/rules/documentation/guide-mentions-documents.ts
5265
5304
  import { existsSync as existsSync3 } from "fs";
5266
- import path46 from "path";
5305
+ import path47 from "path";
5267
5306
  function visitSteps3(node, check) {
5268
5307
  if (node.type === "list" && node.ordered) {
5269
5308
  for (const child of node.children) check(child);
@@ -5296,12 +5335,12 @@ var guideMentionsDocumentsRule = {
5296
5335
  if (!filename.endsWith("-guide.md")) return;
5297
5336
  const docsRoot = findDocsRoot(filename);
5298
5337
  if (!docsRoot) return;
5299
- const guideDir = path46.dirname(filename);
5300
- if (path46.basename(filename, ".md") !== path46.basename(guideDir)) return;
5338
+ const guideDir = path47.dirname(filename);
5339
+ if (path47.basename(filename, ".md") !== path47.basename(guideDir)) return;
5301
5340
  const docs = getProjectDocs(docsRoot);
5302
5341
  const owned = docs.filter((doc) => {
5303
- const parent = path46.dirname(doc.filePath);
5304
- return parent === path46.join(guideDir, "rules") || parent === path46.join(guideDir, "references");
5342
+ const parent = path47.dirname(doc.filePath);
5343
+ return parent === path47.join(guideDir, "rules") || parent === path47.join(guideDir, "references");
5305
5344
  });
5306
5345
  const allLinks = [];
5307
5346
  collectMarkdownLinks(node, allLinks);
@@ -5328,7 +5367,7 @@ var guideMentionsDocumentsRule = {
5328
5367
  for (const link of allLinks) {
5329
5368
  const target = linkTarget(link.url);
5330
5369
  if (!target.endsWith(".md")) continue;
5331
- const resolved = path46.normalize(path46.join(guideDir, target));
5370
+ const resolved = path47.normalize(path47.join(guideDir, target));
5332
5371
  if (!existsSync3(resolved)) {
5333
5372
  context.report({
5334
5373
  node: link,
@@ -5878,11 +5917,11 @@ var themeVariableNamespaceRule = {
5878
5917
 
5879
5918
  // eslint/rules/tailwind/css-entry-point.ts
5880
5919
  import { statSync as statSync6 } from "fs";
5881
- import path49 from "path";
5920
+ import path50 from "path";
5882
5921
 
5883
5922
  // eslint/rules/tailwind/source-files.ts
5884
5923
  import { readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
5885
- import path47 from "path";
5924
+ import path48 from "path";
5886
5925
  var CSS_EXTENSIONS = [".css"];
5887
5926
  var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
5888
5927
  var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS3, ...CSS_EXTENSIONS];
@@ -5895,7 +5934,7 @@ function findFiles(dir, extensions) {
5895
5934
  }
5896
5935
  return entries.flatMap((entry) => {
5897
5936
  if (entry.startsWith(".") || entry === "node_modules") return [];
5898
- const entryPath = path47.join(dir, entry);
5937
+ const entryPath = path48.join(dir, entry);
5899
5938
  let stats;
5900
5939
  try {
5901
5940
  stats = statSync5(entryPath);
@@ -5903,7 +5942,7 @@ function findFiles(dir, extensions) {
5903
5942
  return [];
5904
5943
  }
5905
5944
  if (stats.isDirectory()) return findFiles(entryPath, extensions);
5906
- return extensions.includes(path47.extname(entry)) ? [entryPath] : [];
5945
+ return extensions.includes(path48.extname(entry)) ? [entryPath] : [];
5907
5946
  });
5908
5947
  }
5909
5948
  function cachedTextReader() {
@@ -5926,7 +5965,7 @@ function escapeRegExp(text) {
5926
5965
  }
5927
5966
 
5928
5967
  // eslint/rules/tailwind/stylesheet-graph.ts
5929
- import path48 from "path";
5968
+ import path49 from "path";
5930
5969
  function registersTailwind(text) {
5931
5970
  return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
5932
5971
  }
@@ -5940,25 +5979,25 @@ function moduleImports(text, fileName) {
5940
5979
  return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
5941
5980
  }
5942
5981
  function resolveSpecifier2(fromFile, spec, sourceRoot) {
5943
- if (spec.startsWith("/")) return path48.resolve(spec);
5944
- if (spec.startsWith("./") || spec.startsWith("../")) return path48.resolve(path48.dirname(fromFile), spec);
5945
- if (spec.startsWith("@/")) return path48.resolve(sourceRoot, spec.slice(2));
5982
+ if (spec.startsWith("/")) return path49.resolve(spec);
5983
+ if (spec.startsWith("./") || spec.startsWith("../")) return path49.resolve(path49.dirname(fromFile), spec);
5984
+ if (spec.startsWith("@/")) return path49.resolve(sourceRoot, spec.slice(2));
5946
5985
  return void 0;
5947
5986
  }
5948
5987
  function buildStylesheetGraph(options) {
5949
5988
  const { cssFiles, sourceRoot, textOf } = options;
5950
- const cssSet = new Set(cssFiles.map((file) => path48.normalize(file)));
5989
+ const cssSet = new Set(cssFiles.map((file) => path49.normalize(file)));
5951
5990
  const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
5952
5991
  const reachable = /* @__PURE__ */ new Set();
5953
5992
  const queue = [...globals];
5954
- for (const global of globals) reachable.add(path48.normalize(global));
5993
+ for (const global of globals) reachable.add(path49.normalize(global));
5955
5994
  while (queue.length > 0) {
5956
5995
  const from = queue.shift();
5957
5996
  if (!from) continue;
5958
5997
  for (const spec of importedSpecifiers(textOf(from))) {
5959
5998
  const target = resolveSpecifier2(from, spec, sourceRoot);
5960
5999
  if (!target) continue;
5961
- const normalized = path48.normalize(target);
6000
+ const normalized = path49.normalize(target);
5962
6001
  if (cssSet.has(normalized) && !reachable.has(normalized)) {
5963
6002
  reachable.add(normalized);
5964
6003
  queue.push(normalized);
@@ -5970,7 +6009,7 @@ function buildStylesheetGraph(options) {
5970
6009
  for (const spec of importedSpecifiers(textOf(global))) {
5971
6010
  const target = resolveSpecifier2(global, spec, sourceRoot);
5972
6011
  if (!target) continue;
5973
- const normalized = path48.normalize(target);
6012
+ const normalized = path49.normalize(target);
5974
6013
  if (cssSet.has(normalized)) directChildren.add(normalized);
5975
6014
  }
5976
6015
  }
@@ -6003,7 +6042,7 @@ var cssEntryPointRule = {
6003
6042
  return {
6004
6043
  "StyleSheet:exit"(node) {
6005
6044
  if (globals.length === 0) return;
6006
- const current = path49.normalize(path49.resolve(context.filename));
6045
+ const current = path50.normalize(path50.resolve(context.filename));
6007
6046
  if (globals.includes(current)) {
6008
6047
  if (globals.length > 1) {
6009
6048
  context.report({
@@ -6012,7 +6051,7 @@ var cssEntryPointRule = {
6012
6051
  });
6013
6052
  return;
6014
6053
  }
6015
- const basename = path49.basename(current);
6054
+ const basename = path50.basename(current);
6016
6055
  const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
6017
6056
  if (importCount !== 1) {
6018
6057
  context.report({
@@ -6341,7 +6380,7 @@ var nextjsStackRule = {
6341
6380
 
6342
6381
  // eslint/rules/package-json/vitest-coverage.ts
6343
6382
  import { existsSync as existsSync4, readFileSync as readFileSync9 } from "fs";
6344
- import path50 from "path";
6383
+ import path51 from "path";
6345
6384
  function memberName4(member) {
6346
6385
  return member.name.type === "String" ? member.name.value : member.name.name;
6347
6386
  }
@@ -6410,7 +6449,7 @@ var vitestCoverageRule = {
6410
6449
  message: 'package.json must declare a "test:unit:coverage" script that runs Vitest with coverage.'
6411
6450
  });
6412
6451
  }
6413
- const configName = VITEST_CONFIG_NAMES.find((name) => existsSync4(path50.join(context.cwd, name)));
6452
+ const configName = VITEST_CONFIG_NAMES.find((name) => existsSync4(path51.join(context.cwd, name)));
6414
6453
  if (!configName) {
6415
6454
  context.report({
6416
6455
  node,
@@ -6418,7 +6457,7 @@ var vitestCoverageRule = {
6418
6457
  });
6419
6458
  return;
6420
6459
  }
6421
- const content = readFileSync9(path50.join(context.cwd, configName), "utf8");
6460
+ const content = readFileSync9(path51.join(context.cwd, configName), "utf8");
6422
6461
  for (const metric of THRESHOLD_METRICS) {
6423
6462
  if (!new RegExp(`\\b${metric}\\s*:\\s*[1-9]\\d*`).test(content)) {
6424
6463
  context.report({ node, message: `${configName} must set a coverage threshold above zero for ${metric}.` });
@@ -6465,7 +6504,7 @@ var nextjsPackageJsonRules = {
6465
6504
 
6466
6505
  // eslint/rules/husky/husky-hook.ts
6467
6506
  import { existsSync as existsSync5, readFileSync as readFileSync10 } from "fs";
6468
- import path51 from "path";
6507
+ import path52 from "path";
6469
6508
  var VITEST_CONFIG_NAMES2 = [
6470
6509
  "vitest.config.ts",
6471
6510
  "vitest.config.mts",
@@ -6491,7 +6530,7 @@ var huskyHookRule = {
6491
6530
  const root = node.body;
6492
6531
  if (root.type !== "Object") return;
6493
6532
  if (!context.filename.endsWith("package.json")) return;
6494
- const hookPath = path51.join(context.cwd, ".husky", "pre-commit");
6533
+ const hookPath = path52.join(context.cwd, ".husky", "pre-commit");
6495
6534
  if (!existsSync5(hookPath)) {
6496
6535
  context.report({
6497
6536
  node,
@@ -6515,7 +6554,7 @@ var huskyHookRule = {
6515
6554
  }
6516
6555
  requireNamedScript("typecheck");
6517
6556
  requireNamedScript("test:unit:coverage");
6518
- const vitestConfigName = VITEST_CONFIG_NAMES2.find((name) => existsSync5(path51.join(context.cwd, name)));
6557
+ const vitestConfigName = VITEST_CONFIG_NAMES2.find((name) => existsSync5(path52.join(context.cwd, name)));
6519
6558
  if (vitestConfigName !== void 0) {
6520
6559
  const coverageIndex = content.indexOf("npm run test:unit:coverage");
6521
6560
  const localAddIndex = content.indexOf(`git add ${vitestConfigName}`);
@@ -6529,7 +6568,7 @@ var huskyHookRule = {
6529
6568
  if (!content.includes("libyear --limit-major-individual=1")) {
6530
6569
  context.report({ node, message: ".husky/pre-commit must run npx libyear --limit-major-individual=1." });
6531
6570
  }
6532
- const suppressionsPath = path51.join(context.cwd, "eslint-suppressions.json");
6571
+ const suppressionsPath = path52.join(context.cwd, "eslint-suppressions.json");
6533
6572
  if (existsSync5(suppressionsPath)) {
6534
6573
  requireNamedScript("lint:prune");
6535
6574
  const pruneIndex = content.indexOf("npm run lint:prune");
@@ -6602,7 +6641,7 @@ var vulykDependencyRule = {
6602
6641
 
6603
6642
  // eslint/rules/vulyk/vulyk-docs.ts
6604
6643
  import { existsSync as existsSync6, readFileSync as readFileSync11 } from "fs";
6605
- import path52 from "path";
6644
+ import path53 from "path";
6606
6645
  var PASIKA_REPO = "Bredansky/pasika";
6607
6646
  var BASE_REQUIRED_DOCS = [
6608
6647
  { name: "documentation-guide", path: "docs/documentation-guide" },
@@ -6635,8 +6674,8 @@ var vulykDocsRule = {
6635
6674
  if (!context.filename.endsWith("package.json")) return;
6636
6675
  const root = node.body;
6637
6676
  if (root.type !== "Object") return;
6638
- const projectRoot = path52.dirname(path52.resolve(context.filename));
6639
- const configPath = path52.join(projectRoot, "vulyk.config.ts");
6677
+ const projectRoot = path53.dirname(path53.resolve(context.filename));
6678
+ const configPath = path53.join(projectRoot, "vulyk.config.ts");
6640
6679
  if (!existsSync6(configPath)) {
6641
6680
  context.report({
6642
6681
  node,
@@ -6661,7 +6700,7 @@ var vulykDocsRule = {
6661
6700
  });
6662
6701
  }
6663
6702
  }
6664
- const agentsPath = path52.join(projectRoot, "AGENTS.md");
6703
+ const agentsPath = path53.join(projectRoot, "AGENTS.md");
6665
6704
  if (!existsSync6(agentsPath)) {
6666
6705
  context.report({
6667
6706
  node,
@@ -6694,6 +6733,7 @@ var pasikaNextjsAppRules = {
6694
6733
  "config-extraction": configExtractionRule,
6695
6734
  "value-extraction": valueExtractionRule,
6696
6735
  "constant-casing": constantCasingRule,
6736
+ "prefer-enum": preferEnumRule,
6697
6737
  "type-extraction": typeExtractionRule,
6698
6738
  "zod-schema-validation": zodSchemaValidationRule,
6699
6739
  "schema-casing": schemaCasingRule,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",