@yasainet/eslint 0.0.73 → 0.0.75
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 +9 -152
- package/package.json +7 -1
- package/src/cli/test-audit.mjs +97 -0
- package/src/common/CLAUDE.md +17 -0
- package/src/common/{constants.mjs → _internal/constants.mjs} +1 -19
- package/src/common/_internal/import-patterns.mjs +16 -0
- package/src/common/{plugins.mjs → _internal/plugins.mjs} +0 -1
- package/src/common/_internal/selectors.mjs +12 -0
- package/src/common/{rules.mjs → base/typescript.mjs} +15 -36
- package/src/common/{entry-points.mjs → boundaries/entry-point.mjs} +1 -2
- package/src/common/cross-cutting/ban-alias.mjs +22 -0
- package/src/common/cross-cutting/feature-default-imports.mjs +26 -0
- package/src/common/cross-cutting/feature-name.mjs +15 -0
- package/src/common/cross-cutting/features-ts-only.mjs +20 -0
- package/src/common/cross-cutting/form-state.mjs +16 -0
- package/src/common/{jsdoc.mjs → cross-cutting/jsdoc.mjs} +2 -3
- package/src/common/cross-cutting/logger.mjs +21 -0
- package/src/common/cross-cutting/namespace-import.mjs +23 -0
- package/src/common/cross-cutting/no-any-return.mjs +18 -0
- package/src/common/cross-cutting/no-colocated-test.mjs +18 -0
- package/src/common/cross-cutting/supabase-columns-satisfies.mjs +18 -0
- package/src/common/index.mjs +44 -24
- package/src/common/layers/constants.mjs +36 -0
- package/src/common/layers/entries.mjs +174 -0
- package/src/common/layers/lib.mjs +18 -0
- package/src/common/layers/queries.mjs +187 -0
- package/src/common/layers/schemas.mjs +50 -0
- package/src/common/layers/services.mjs +121 -0
- package/src/common/layers/top-level-utils.mjs +18 -0
- package/src/common/layers/types.mjs +44 -0
- package/src/common/layers/utils.mjs +54 -0
- package/src/common/local-plugins/entry-single-service-call.mjs +3 -31
- package/src/common/local-plugins/entry-template.mjs +51 -88
- package/src/common/local-plugins/feature-name.mjs +5 -24
- package/src/common/local-plugins/form-state-naming.mjs +1 -11
- package/src/common/local-plugins/form-state-shape.mjs +8 -42
- package/src/common/local-plugins/import-path-style.mjs +2 -9
- package/src/common/local-plugins/index.mjs +2 -1
- package/src/common/local-plugins/layout-main-structural-only.mjs +1 -22
- package/src/common/local-plugins/namespace-import-name.mjs +1 -27
- package/src/common/local-plugins/no-any-return.mjs +1 -9
- package/src/common/local-plugins/no-colocated-test.mjs +26 -0
- package/src/common/local-plugins/queries-export.mjs +1 -9
- package/src/common/local-plugins/queries-namespace-import.mjs +1 -11
- package/src/common/local-plugins/schema-naming.mjs +2 -8
- package/src/common/local-plugins/supabase-columns-satisfies.mjs +1 -25
- package/src/common/local-plugins/supabase-select-typed-columns.mjs +5 -37
- package/src/deno/CLAUDE.md +10 -0
- package/src/deno/boundaries/entry-point.mjs +44 -0
- package/src/deno/boundaries/lib.mjs +28 -0
- package/src/deno/boundaries/utils.mjs +25 -0
- package/src/deno/index.mjs +9 -13
- package/src/deno/local-plugins/flat-entry-point.mjs +1 -6
- package/src/deno/local-plugins/index.mjs +0 -1
- package/src/next/CLAUDE.md +14 -0
- package/src/next/boundaries/components.mjs +36 -0
- package/src/next/boundaries/hooks.mjs +36 -0
- package/src/next/boundaries/lib.mjs +23 -0
- package/src/next/boundaries/page.mjs +36 -0
- package/src/next/boundaries/route.mjs +36 -0
- package/src/next/boundaries/sitemap.mjs +36 -0
- package/src/next/directives.mjs +4 -5
- package/src/next/imports.mjs +0 -1
- package/src/next/index.mjs +12 -15
- package/src/next/layers/components.mjs +30 -0
- package/src/next/layers/hooks.mjs +31 -0
- package/src/next/layers/layouts.mjs +12 -0
- package/src/next/tailwindcss.mjs +2 -23
- package/src/node/CLAUDE.md +7 -0
- package/src/node/index.mjs +1 -2
- package/src/common/imports.mjs +0 -457
- package/src/common/layers.mjs +0 -158
- package/src/common/naming.mjs +0 -347
- package/src/deno/imports.mjs +0 -90
- package/src/next/layouts.mjs +0 -18
- package/src/next/naming.mjs +0 -60
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { featuresGlob } from "../_internal/constants.mjs";
|
|
2
|
+
import { localPlugin } from "../local-plugins/index.mjs";
|
|
3
|
+
|
|
4
|
+
export function createNamespaceImportConfigs({ featureRoot }) {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
name: "naming/namespace-import-name",
|
|
8
|
+
files: featuresGlob(featureRoot, "**/*.ts"),
|
|
9
|
+
plugins: { local: localPlugin },
|
|
10
|
+
rules: {
|
|
11
|
+
"local/namespace-import-name": ["error", { featureRoot }],
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: "naming/queries-namespace-import",
|
|
16
|
+
files: featuresGlob(featureRoot, "**/*.ts"),
|
|
17
|
+
plugins: { local: localPlugin },
|
|
18
|
+
rules: {
|
|
19
|
+
"local/queries-namespace-import": "error",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { localPlugin } from "../local-plugins/index.mjs";
|
|
2
|
+
|
|
3
|
+
export function createNoAnyReturnConfigs({ featureRoot, typeAware }) {
|
|
4
|
+
if (!typeAware) return [];
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
name: "layers/no-any-return",
|
|
8
|
+
files: [
|
|
9
|
+
`${featureRoot}/**/queries/*.ts`,
|
|
10
|
+
`${featureRoot}/**/services/*.ts`,
|
|
11
|
+
],
|
|
12
|
+
plugins: { local: localPlugin },
|
|
13
|
+
rules: {
|
|
14
|
+
"local/no-any-return": "error",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { localPlugin } from "../local-plugins/index.mjs";
|
|
2
|
+
|
|
3
|
+
export function createNoColocatedTestConfigs({ featureRoot }) {
|
|
4
|
+
return [
|
|
5
|
+
{
|
|
6
|
+
name: "test/no-colocated-test",
|
|
7
|
+
files: [
|
|
8
|
+
`${featureRoot}/**/services/**/*.test.{ts,tsx}`,
|
|
9
|
+
`${featureRoot}/**/queries/**/*.test.{ts,tsx}`,
|
|
10
|
+
`${featureRoot}/**/entries/**/*.test.{ts,tsx}`,
|
|
11
|
+
],
|
|
12
|
+
plugins: { local: localPlugin },
|
|
13
|
+
rules: {
|
|
14
|
+
"local/no-colocated-test": "error",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { featuresGlob } from "../_internal/constants.mjs";
|
|
2
|
+
import { localPlugin } from "../local-plugins/index.mjs";
|
|
3
|
+
|
|
4
|
+
export function createSupabaseColumnsSatisfiesConfigs({ featureRoot }) {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
name: "naming/supabase-columns-satisfies",
|
|
8
|
+
files: [
|
|
9
|
+
...featuresGlob(featureRoot, "**/queries/*.ts"),
|
|
10
|
+
...featuresGlob(featureRoot, "**/constants/*.ts"),
|
|
11
|
+
],
|
|
12
|
+
plugins: { local: localPlugin },
|
|
13
|
+
rules: {
|
|
14
|
+
"local/supabase-columns-satisfies": "error",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
}
|
package/src/common/index.mjs
CHANGED
|
@@ -1,33 +1,53 @@
|
|
|
1
|
-
import { generatePrefixLibMapping } from "./constants.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { generatePrefixLibMapping } from "./_internal/constants.mjs";
|
|
2
|
+
import { createTypescriptConfigs } from "./base/typescript.mjs";
|
|
3
|
+
import { createBanAliasConfigs } from "./cross-cutting/ban-alias.mjs";
|
|
4
|
+
import { createFeatureDefaultImportsConfigs } from "./cross-cutting/feature-default-imports.mjs";
|
|
5
|
+
import { createFeatureNameConfigs } from "./cross-cutting/feature-name.mjs";
|
|
6
|
+
import { createFeaturesTsOnlyConfigs } from "./cross-cutting/features-ts-only.mjs";
|
|
7
|
+
import { createFormStateConfigs } from "./cross-cutting/form-state.mjs";
|
|
8
|
+
import { createJsdocConfigs } from "./cross-cutting/jsdoc.mjs";
|
|
9
|
+
import { createLoggerConfigs } from "./cross-cutting/logger.mjs";
|
|
10
|
+
import { createNamespaceImportConfigs } from "./cross-cutting/namespace-import.mjs";
|
|
11
|
+
import { createNoAnyReturnConfigs } from "./cross-cutting/no-any-return.mjs";
|
|
12
|
+
import { createNoColocatedTestConfigs } from "./cross-cutting/no-colocated-test.mjs";
|
|
13
|
+
import { createSupabaseColumnsSatisfiesConfigs } from "./cross-cutting/supabase-columns-satisfies.mjs";
|
|
14
|
+
import { createConstantsConfigs } from "./layers/constants.mjs";
|
|
15
|
+
import { createEntriesConfigs } from "./layers/entries.mjs";
|
|
16
|
+
import { createLibLayerConfigs } from "./layers/lib.mjs";
|
|
17
|
+
import { createQueriesConfigs } from "./layers/queries.mjs";
|
|
18
|
+
import { createSchemasConfigs } from "./layers/schemas.mjs";
|
|
19
|
+
import { createServicesConfigs } from "./layers/services.mjs";
|
|
20
|
+
import { createTopLevelUtilsConfigs } from "./layers/top-level-utils.mjs";
|
|
21
|
+
import { createTypesConfigs } from "./layers/types.mjs";
|
|
22
|
+
import { createUtilsConfigs } from "./layers/utils.mjs";
|
|
7
23
|
|
|
8
|
-
/**
|
|
9
|
-
* Build common configs scoped to the given feature root:
|
|
10
|
-
*
|
|
11
|
-
* - `banAliasImports: true` enforces relative imports inside the feature root
|
|
12
|
-
* - `typeAware: false` disables type-aware rules and `local/no-any-return`,
|
|
13
|
-
* for environments without a project tsconfig (e.g., Deno entry)
|
|
14
|
-
* - `rulesFiles` narrows the parser/rules block. Pass when combining multiple
|
|
15
|
-
* entries so each entry only overrides its own files (e.g., the deno entry
|
|
16
|
-
* passes `["supabase/functions/**\/*.ts"]` so it doesn't override next's
|
|
17
|
-
* parser settings on `src/`).
|
|
18
|
-
*/
|
|
19
24
|
export function createCommonConfigs(
|
|
20
25
|
featureRoot,
|
|
21
26
|
{ banAliasImports = false, typeAware = true, rulesFiles } = {},
|
|
22
27
|
) {
|
|
23
28
|
const prefixLibMapping = generatePrefixLibMapping(featureRoot);
|
|
29
|
+
const ctx = { featureRoot, prefixLibMapping, typeAware };
|
|
24
30
|
return [
|
|
25
|
-
...
|
|
26
|
-
...
|
|
27
|
-
...
|
|
28
|
-
...
|
|
29
|
-
...
|
|
30
|
-
...
|
|
31
|
-
...
|
|
31
|
+
...createTypescriptConfigs({ typeAware, ...(rulesFiles && { files: rulesFiles }) }),
|
|
32
|
+
...createFeatureNameConfigs(ctx),
|
|
33
|
+
...createNamespaceImportConfigs(ctx),
|
|
34
|
+
...createServicesConfigs(ctx),
|
|
35
|
+
...createQueriesConfigs(ctx),
|
|
36
|
+
...createFormStateConfigs(ctx),
|
|
37
|
+
...createSupabaseColumnsSatisfiesConfigs(ctx),
|
|
38
|
+
...createLibLayerConfigs(ctx),
|
|
39
|
+
...createTopLevelUtilsConfigs(ctx),
|
|
40
|
+
...createTypesConfigs(ctx),
|
|
41
|
+
...createSchemasConfigs(ctx),
|
|
42
|
+
...createUtilsConfigs(ctx),
|
|
43
|
+
...createConstantsConfigs(ctx),
|
|
44
|
+
...createEntriesConfigs(ctx),
|
|
45
|
+
...createFeaturesTsOnlyConfigs(ctx),
|
|
46
|
+
...createNoColocatedTestConfigs(ctx),
|
|
47
|
+
...createLoggerConfigs(ctx),
|
|
48
|
+
...createNoAnyReturnConfigs(ctx),
|
|
49
|
+
...createFeatureDefaultImportsConfigs(ctx),
|
|
50
|
+
...createJsdocConfigs(ctx),
|
|
51
|
+
...(banAliasImports ? createBanAliasConfigs(ctx) : []),
|
|
32
52
|
];
|
|
33
53
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { featuresGlob } from "../_internal/constants.mjs";
|
|
2
|
+
import { checkFile } from "../_internal/plugins.mjs";
|
|
3
|
+
|
|
4
|
+
export function createConstantsConfigs({ featureRoot, prefixLibMapping }) {
|
|
5
|
+
const prefixes = Object.keys(prefixLibMapping);
|
|
6
|
+
const hasPrefixes = prefixes.length > 0;
|
|
7
|
+
const sharedPrefixPattern = hasPrefixes
|
|
8
|
+
? `@(shared|${prefixes.join("|")})`
|
|
9
|
+
: "shared";
|
|
10
|
+
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
name: "naming/constants",
|
|
14
|
+
files: featuresGlob(featureRoot, "*/constants/*.ts"),
|
|
15
|
+
ignores: featuresGlob(featureRoot, "shared/constants/*.ts"),
|
|
16
|
+
plugins: { "check-file": checkFile },
|
|
17
|
+
rules: {
|
|
18
|
+
"check-file/filename-naming-convention": [
|
|
19
|
+
"error",
|
|
20
|
+
{ "**/*/constants/*.ts": "<1>" },
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "naming/constants-shared",
|
|
26
|
+
files: featuresGlob(featureRoot, "shared/constants/*.ts"),
|
|
27
|
+
plugins: { "check-file": checkFile },
|
|
28
|
+
rules: {
|
|
29
|
+
"check-file/filename-naming-convention": [
|
|
30
|
+
"error",
|
|
31
|
+
{ "**/*.ts": sharedPrefixPattern },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { featuresGlob } from "../_internal/constants.mjs";
|
|
2
|
+
import {
|
|
3
|
+
LIB_BOUNDARY_PATTERNS,
|
|
4
|
+
MAPPING_PATTERNS,
|
|
5
|
+
} from "../_internal/import-patterns.mjs";
|
|
6
|
+
import { checkFile } from "../_internal/plugins.mjs";
|
|
7
|
+
import {
|
|
8
|
+
aliasDynamicImportMessage,
|
|
9
|
+
aliasDynamicImportSelector,
|
|
10
|
+
} from "../_internal/selectors.mjs";
|
|
11
|
+
import { localPlugin } from "../local-plugins/index.mjs";
|
|
12
|
+
|
|
13
|
+
const LAYER_PATTERNS = [
|
|
14
|
+
{
|
|
15
|
+
group: ["**/queries/*", "**/queries"],
|
|
16
|
+
message:
|
|
17
|
+
"entries は queries を import 不可。queries は service 経由で使う。",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
group: ["**/hooks/*", "**/hooks"],
|
|
21
|
+
message: "entries は hooks を import 不可。依存は単方向に保つ。",
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const LATERAL_PATTERNS = [
|
|
26
|
+
{
|
|
27
|
+
group: ["@/features/*/entries/*", "@/features/*/entries"],
|
|
28
|
+
message: "他 feature の entries は import 不可。feature を跨ぐ依存は禁止。",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
group: [
|
|
32
|
+
"@/features/*/services/*",
|
|
33
|
+
"@/features/*/services",
|
|
34
|
+
"!@/features/shared/services/*",
|
|
35
|
+
"!@/features/shared/services",
|
|
36
|
+
],
|
|
37
|
+
message:
|
|
38
|
+
"他 feature の services は import 不可:\n" +
|
|
39
|
+
"- 同一 feature の service を 1:1 で使うか、orchestration を service 層へ移す\n" +
|
|
40
|
+
"- `shared/services/*` は横断的な副作用 (通知等) のため例外",
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const CARDINALITY_PATTERNS = {
|
|
45
|
+
server: [
|
|
46
|
+
{
|
|
47
|
+
group: ["**/services/client", "**/services/admin"],
|
|
48
|
+
message:
|
|
49
|
+
"server entry は server service のみ import 可。context を跨ぐ呼び出しは禁止。",
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
client: [
|
|
53
|
+
{
|
|
54
|
+
group: ["**/services/server", "**/services/admin"],
|
|
55
|
+
message:
|
|
56
|
+
"client entry は client service のみ import 可。context を跨ぐ呼び出しは禁止。",
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
admin: [
|
|
60
|
+
{
|
|
61
|
+
group: ["**/services/server", "**/services/client"],
|
|
62
|
+
message:
|
|
63
|
+
"admin entry は admin service のみ import 可。context を跨ぐ呼び出しは禁止。",
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export function createEntriesConfigs({ featureRoot, prefixLibMapping }) {
|
|
69
|
+
const prefixes = Object.keys(prefixLibMapping);
|
|
70
|
+
const hasPrefixes = prefixes.length > 0;
|
|
71
|
+
const prefixPattern = hasPrefixes ? `@(${prefixes.join("|")})` : "*";
|
|
72
|
+
const sharedPrefixPattern = hasPrefixes
|
|
73
|
+
? `@(shared|${prefixes.join("|")})`
|
|
74
|
+
: "shared";
|
|
75
|
+
|
|
76
|
+
const configs = [
|
|
77
|
+
{
|
|
78
|
+
name: "naming/entries",
|
|
79
|
+
files: featuresGlob(featureRoot, "**/entries/*.ts"),
|
|
80
|
+
ignores: [
|
|
81
|
+
...featuresGlob(featureRoot, "shared/entries/*.ts"),
|
|
82
|
+
"**/*.test.ts",
|
|
83
|
+
],
|
|
84
|
+
plugins: { "check-file": checkFile },
|
|
85
|
+
rules: {
|
|
86
|
+
"check-file/filename-naming-convention": [
|
|
87
|
+
"error",
|
|
88
|
+
{ "**/*.ts": prefixPattern },
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "naming/entries-shared",
|
|
94
|
+
files: featuresGlob(featureRoot, "shared/entries/*.ts"),
|
|
95
|
+
ignores: ["**/*.test.ts"],
|
|
96
|
+
plugins: { "check-file": checkFile },
|
|
97
|
+
rules: {
|
|
98
|
+
"check-file/filename-naming-convention": [
|
|
99
|
+
"error",
|
|
100
|
+
{ "**/*.ts": sharedPrefixPattern },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "naming/entry-template",
|
|
106
|
+
files: featuresGlob(featureRoot, "**/entries/*.ts"),
|
|
107
|
+
plugins: { local: localPlugin },
|
|
108
|
+
rules: {
|
|
109
|
+
"local/entry-template": "error",
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "naming/entry-single-service-call",
|
|
114
|
+
files: featuresGlob(featureRoot, "**/entries/*.ts"),
|
|
115
|
+
plugins: { local: localPlugin },
|
|
116
|
+
rules: {
|
|
117
|
+
"local/entry-single-service-call": "error",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "layers/entries",
|
|
122
|
+
files: [`${featureRoot}/**/entries/*.ts`],
|
|
123
|
+
rules: {
|
|
124
|
+
"no-restricted-syntax": [
|
|
125
|
+
"error",
|
|
126
|
+
{
|
|
127
|
+
selector: aliasDynamicImportSelector,
|
|
128
|
+
message: aliasDynamicImportMessage,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "imports/entries",
|
|
135
|
+
files: [`${featureRoot}/**/entries/*.ts`],
|
|
136
|
+
rules: {
|
|
137
|
+
"no-restricted-imports": [
|
|
138
|
+
"error",
|
|
139
|
+
{
|
|
140
|
+
patterns: [
|
|
141
|
+
...LAYER_PATTERNS,
|
|
142
|
+
...LATERAL_PATTERNS,
|
|
143
|
+
...LIB_BOUNDARY_PATTERNS,
|
|
144
|
+
...MAPPING_PATTERNS,
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
for (const prefix of ["server", "client", "admin"]) {
|
|
153
|
+
configs.push({
|
|
154
|
+
name: `imports/entries/${prefix}`,
|
|
155
|
+
files: [`${featureRoot}/**/entries/${prefix}.ts`],
|
|
156
|
+
rules: {
|
|
157
|
+
"no-restricted-imports": [
|
|
158
|
+
"error",
|
|
159
|
+
{
|
|
160
|
+
patterns: [
|
|
161
|
+
...LAYER_PATTERNS,
|
|
162
|
+
...LATERAL_PATTERNS,
|
|
163
|
+
...CARDINALITY_PATTERNS[prefix],
|
|
164
|
+
...LIB_BOUNDARY_PATTERNS,
|
|
165
|
+
...MAPPING_PATTERNS,
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return configs;
|
|
174
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { checkFile } from "../_internal/plugins.mjs";
|
|
2
|
+
|
|
3
|
+
export function createLibLayerConfigs({ featureRoot }) {
|
|
4
|
+
const libRoot = featureRoot.replace(/features$/, "lib");
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
name: "naming/lib",
|
|
8
|
+
files: [`${libRoot}/**/*.ts`],
|
|
9
|
+
plugins: { "check-file": checkFile },
|
|
10
|
+
rules: {
|
|
11
|
+
"check-file/filename-naming-convention": [
|
|
12
|
+
"error",
|
|
13
|
+
{ "**/*.ts": "*" },
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { featuresGlob } from "../_internal/constants.mjs";
|
|
2
|
+
import { MAPPING_PATTERNS } from "../_internal/import-patterns.mjs";
|
|
3
|
+
import { checkFile } from "../_internal/plugins.mjs";
|
|
4
|
+
import {
|
|
5
|
+
aliasDynamicImportMessage,
|
|
6
|
+
aliasDynamicImportSelector,
|
|
7
|
+
loggerMessage,
|
|
8
|
+
loggerSelector,
|
|
9
|
+
} from "../_internal/selectors.mjs";
|
|
10
|
+
import { localPlugin } from "../local-plugins/index.mjs";
|
|
11
|
+
|
|
12
|
+
const LAYER_PATTERNS = [
|
|
13
|
+
{
|
|
14
|
+
group: ["**/services/*", "**/services"],
|
|
15
|
+
message: "queries は services を import 不可。ロジックは services へ。",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
group: ["**/entries/*", "**/entries"],
|
|
19
|
+
message: "queries は entries を import 不可。依存は単方向に保つ。",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
group: ["**/hooks/*", "**/hooks"],
|
|
23
|
+
message: "queries は hooks を import 不可。依存は単方向に保つ。",
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const LATERAL_PATTERNS = [
|
|
28
|
+
{
|
|
29
|
+
group: ["@/features/*/queries/*", "@/features/*/queries"],
|
|
30
|
+
message:
|
|
31
|
+
"他 feature の queries は import 不可。feature を跨ぐ依存は禁止。",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
function prefixLibPatterns(prefix, mapping) {
|
|
36
|
+
const prefixes = Object.keys(mapping);
|
|
37
|
+
const allowedLib = mapping[prefix];
|
|
38
|
+
return prefixes
|
|
39
|
+
.filter((p) => p !== prefix)
|
|
40
|
+
.map((p) => ({
|
|
41
|
+
group: [`**/lib/${mapping[p]}`, `**/lib/${mapping[p]}/*`],
|
|
42
|
+
message: `queries/${prefix}.ts は lib/${allowedLib} のみ import 可。lib ごとに対応する query file を使う。`,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function createQueriesConfigs({ featureRoot, prefixLibMapping }) {
|
|
47
|
+
const prefixes = Object.keys(prefixLibMapping);
|
|
48
|
+
const hasPrefixes = prefixes.length > 0;
|
|
49
|
+
const prefixPattern = hasPrefixes ? `@(${prefixes.join("|")})` : "*";
|
|
50
|
+
const sharedPrefixPattern = hasPrefixes
|
|
51
|
+
? `@(shared|${prefixes.join("|")})`
|
|
52
|
+
: "shared";
|
|
53
|
+
|
|
54
|
+
const configs = [
|
|
55
|
+
{
|
|
56
|
+
name: "naming/queries",
|
|
57
|
+
files: featuresGlob(featureRoot, "**/queries/*.ts"),
|
|
58
|
+
ignores: [
|
|
59
|
+
...featuresGlob(featureRoot, "shared/queries/*.ts"),
|
|
60
|
+
"**/*.test.ts",
|
|
61
|
+
],
|
|
62
|
+
plugins: { "check-file": checkFile },
|
|
63
|
+
rules: {
|
|
64
|
+
"check-file/filename-naming-convention": [
|
|
65
|
+
"error",
|
|
66
|
+
{ "**/*.ts": prefixPattern },
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "naming/queries-shared",
|
|
72
|
+
files: featuresGlob(featureRoot, "shared/queries/*.ts"),
|
|
73
|
+
ignores: ["**/*.test.ts"],
|
|
74
|
+
plugins: { "check-file": checkFile },
|
|
75
|
+
rules: {
|
|
76
|
+
"check-file/filename-naming-convention": [
|
|
77
|
+
"error",
|
|
78
|
+
{ "**/*.ts": sharedPrefixPattern },
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "naming/queries-export",
|
|
84
|
+
files: featuresGlob(featureRoot, "**/queries/*.ts"),
|
|
85
|
+
plugins: { local: localPlugin },
|
|
86
|
+
rules: {
|
|
87
|
+
"local/queries-export": "error",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "naming/supabase-select",
|
|
92
|
+
files: featuresGlob(featureRoot, "**/queries/*.ts"),
|
|
93
|
+
plugins: { local: localPlugin },
|
|
94
|
+
rules: {
|
|
95
|
+
"local/supabase-select-typed-columns": "error",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "layers/queries",
|
|
100
|
+
files: [`${featureRoot}/**/queries/*.ts`],
|
|
101
|
+
rules: {
|
|
102
|
+
"no-restricted-syntax": [
|
|
103
|
+
"error",
|
|
104
|
+
{
|
|
105
|
+
selector: "TryStatement",
|
|
106
|
+
message:
|
|
107
|
+
"queries では try-catch 禁止。エラーは `{ data, error }` で返す。",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
selector: "IfStatement",
|
|
111
|
+
message:
|
|
112
|
+
"queries で if 文は禁止。条件分岐は services に置く。",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
selector: "ForStatement",
|
|
116
|
+
message:
|
|
117
|
+
"queries でループは禁止。queries は薄い CRUD ラッパー、反復は services に置く。",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
selector: "ForOfStatement",
|
|
121
|
+
message:
|
|
122
|
+
"queries でループは禁止。queries は薄い CRUD ラッパー、反復は services に置く。",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
selector: "ForInStatement",
|
|
126
|
+
message:
|
|
127
|
+
"queries でループは禁止。queries は薄い CRUD ラッパー、反復は services に置く。",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
selector: "WhileStatement",
|
|
131
|
+
message:
|
|
132
|
+
"queries でループは禁止。queries は薄い CRUD ラッパー、反復は services に置く。",
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
selector: "DoWhileStatement",
|
|
136
|
+
message:
|
|
137
|
+
"queries でループは禁止。queries は薄い CRUD ラッパー、反復は services に置く。",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
selector: "ThrowStatement",
|
|
141
|
+
message:
|
|
142
|
+
"queries で throw は禁止。Supabase の `{ data, error }` をそのまま返す。",
|
|
143
|
+
},
|
|
144
|
+
{ selector: loggerSelector, message: loggerMessage },
|
|
145
|
+
{
|
|
146
|
+
selector: aliasDynamicImportSelector,
|
|
147
|
+
message: aliasDynamicImportMessage,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "imports/queries",
|
|
154
|
+
files: [`${featureRoot}/**/queries/*.ts`],
|
|
155
|
+
rules: {
|
|
156
|
+
"no-restricted-imports": [
|
|
157
|
+
"error",
|
|
158
|
+
{ patterns: [...LAYER_PATTERNS, ...LATERAL_PATTERNS, ...MAPPING_PATTERNS] },
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
for (const prefix of prefixes) {
|
|
165
|
+
const patterns = prefixLibPatterns(prefix, prefixLibMapping);
|
|
166
|
+
if (patterns.length === 0) continue;
|
|
167
|
+
configs.push({
|
|
168
|
+
name: `imports/queries/${prefix}`,
|
|
169
|
+
files: [`${featureRoot}/**/queries/${prefix}.ts`],
|
|
170
|
+
rules: {
|
|
171
|
+
"no-restricted-imports": [
|
|
172
|
+
"error",
|
|
173
|
+
{
|
|
174
|
+
patterns: [
|
|
175
|
+
...LAYER_PATTERNS,
|
|
176
|
+
...LATERAL_PATTERNS,
|
|
177
|
+
...patterns,
|
|
178
|
+
...MAPPING_PATTERNS,
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return configs;
|
|
187
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { featuresGlob } from "../_internal/constants.mjs";
|
|
2
|
+
import { checkFile } from "../_internal/plugins.mjs";
|
|
3
|
+
import { localPlugin } from "../local-plugins/index.mjs";
|
|
4
|
+
|
|
5
|
+
export function createSchemasConfigs({ featureRoot, prefixLibMapping }) {
|
|
6
|
+
const prefixes = Object.keys(prefixLibMapping);
|
|
7
|
+
const hasPrefixes = prefixes.length > 0;
|
|
8
|
+
const sharedPrefixPattern = hasPrefixes
|
|
9
|
+
? `@(shared|${prefixes.join("|")})`
|
|
10
|
+
: "shared";
|
|
11
|
+
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
name: "naming/schemas",
|
|
15
|
+
files: featuresGlob(featureRoot, "*/schemas/*.ts"),
|
|
16
|
+
ignores: [
|
|
17
|
+
...featuresGlob(featureRoot, "shared/schemas/*.ts"),
|
|
18
|
+
"**/*.test.ts",
|
|
19
|
+
],
|
|
20
|
+
plugins: { "check-file": checkFile },
|
|
21
|
+
rules: {
|
|
22
|
+
"check-file/filename-naming-convention": [
|
|
23
|
+
"error",
|
|
24
|
+
{ "**/*/schemas/*.ts": "<1>" },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "naming/schemas-shared",
|
|
30
|
+
files: featuresGlob(featureRoot, "shared/schemas/*.ts"),
|
|
31
|
+
ignores: ["**/*.test.ts"],
|
|
32
|
+
plugins: { "check-file": checkFile },
|
|
33
|
+
rules: {
|
|
34
|
+
"check-file/filename-naming-convention": [
|
|
35
|
+
"error",
|
|
36
|
+
{ "**/*.ts": sharedPrefixPattern },
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "naming/schema-naming",
|
|
42
|
+
files: featuresGlob(featureRoot, "**/schemas/*.ts"),
|
|
43
|
+
ignores: ["**/*.test.ts"],
|
|
44
|
+
plugins: { local: localPlugin },
|
|
45
|
+
rules: {
|
|
46
|
+
"local/schema-naming": "error",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
}
|