@yasainet/eslint 0.0.27 → 0.0.28

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.
package/README.md CHANGED
@@ -65,6 +65,7 @@ export default defineConfig([
65
65
  globalIgnores([
66
66
  // Default ignores of eslint-config-next:
67
67
  ".next/**",
68
+ ".vercel/**",
68
69
  "out/**",
69
70
  "build/**",
70
71
  "next-env.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yasainet/eslint",
3
- "version": "0.0.27",
3
+ "version": "0.0.28",
4
4
  "description": "ESLint",
5
5
  "type": "module",
6
6
  "exports": {
@@ -42,15 +42,16 @@ function parseImportSource(importPath, featureRoot) {
42
42
 
43
43
  // Only process paths within the feature root
44
44
  const rootPrefix = featureRoot + "/";
45
- if (!normalized.startsWith(rootPrefix)) return null;
45
+ const rootIdx = normalized.indexOf(rootPrefix);
46
+ if (rootIdx === -1) return null;
46
47
 
47
- const afterRoot = normalized.slice(rootPrefix.length);
48
+ const afterRoot = normalized.slice(rootIdx + rootPrefix.length);
48
49
  // Expected: {feature}/{layerDir}/{scope}.{layerExt}
49
50
  const segments = afterRoot.split("/");
50
51
  if (segments.length < 2) return null;
51
52
 
52
53
  const featureDir = segments[0];
53
- const fileName = segments[segments.length - 1];
54
+ const fileName = segments[segments.length - 1].replace(/\.tsx?$/, "");
54
55
 
55
56
  const dotIdx = fileName.indexOf(".");
56
57
  if (dotIdx === -1) return null;
@@ -69,11 +70,6 @@ function buildExpectedName(featureDir, scope, layer) {
69
70
  const featureCamel = toCamelCase(featureDir);
70
71
  const scopePascal = toPascalCase(scope);
71
72
 
72
- // Dedup: if feature is "shared" or featureName === scope, omit feature prefix
73
- if (featureDir === "shared" || featureCamel === scope) {
74
- return scope + layer;
75
- }
76
-
77
73
  return featureCamel + scopePascal + layer;
78
74
  }
79
75
 
@@ -1,3 +1,5 @@
1
+ import { denoLocalPlugin } from "./local-plugins/index.mjs";
2
+
1
3
  const FUNCTIONS_ROOT = "supabase/functions";
2
4
  const FEATURE_ROOT = "supabase/functions/_features";
3
5
 
@@ -76,4 +78,13 @@ export const denoImportsConfigs = [
76
78
  ],
77
79
  },
78
80
  },
81
+ {
82
+ name: "deno/flat-entry-point",
83
+ files: [`${FUNCTIONS_ROOT}/**/*.ts`],
84
+ ignores: [`${FUNCTIONS_ROOT}/_*/**`],
85
+ plugins: { "deno-local": denoLocalPlugin },
86
+ rules: {
87
+ "deno-local/flat-entry-point": "error",
88
+ },
89
+ },
79
90
  ];
@@ -0,0 +1,39 @@
1
+ /** Ensure Edge Function entry points are directly under supabase/functions/. */
2
+ export const flatEntryPointRule = {
3
+ meta: {
4
+ type: "problem",
5
+ messages: {
6
+ nested:
7
+ "Edge Function entry points must be directly under supabase/functions/. Nested directories (e.g., commands/{{name}}) are not supported by Supabase CLI.",
8
+ },
9
+ schema: [],
10
+ },
11
+ create(context) {
12
+ return {
13
+ Program(node) {
14
+ const filename = context.filename ?? context.getFilename();
15
+ const idx = filename.indexOf("supabase/functions/");
16
+ if (idx === -1) return;
17
+
18
+ const relative = filename.slice(idx + "supabase/functions/".length);
19
+ const segments = relative.split("/").filter(Boolean);
20
+
21
+ // _prefix directories are shared code, not entry points
22
+ if (segments[0]?.startsWith("_")) return;
23
+
24
+ // Root-level files (deno.json, .env, etc.) are not entry points
25
+ if (segments.length <= 1) return;
26
+
27
+ // Valid: <name>/index.ts (exactly 2 segments)
28
+ // Invalid: <name>/<nested>/index.ts (3+ segments)
29
+ if (segments.length > 2) {
30
+ context.report({
31
+ node,
32
+ messageId: "nested",
33
+ data: { name: segments.slice(0, -1).join("/") },
34
+ });
35
+ }
36
+ },
37
+ };
38
+ },
39
+ };
@@ -0,0 +1,8 @@
1
+ import { flatEntryPointRule } from "./flat-entry-point.mjs";
2
+
3
+ /** Deno-specific local plugin (independent from common localPlugin). */
4
+ export const denoLocalPlugin = {
5
+ rules: {
6
+ "flat-entry-point": flatEntryPointRule,
7
+ },
8
+ };