@pjts/eslint-style-rules 0.0.3 → 0.0.5

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
@@ -106,15 +106,20 @@ exception is an inline disable with a reason:
106
106
  | Rule | What it checks |
107
107
  |---|---|
108
108
  | `module-layout` | only `rootFiles` at a module root (`<Module>Module.ts`, `<Module>MessageHandlers.ts`, `index.ts`); allowed top-level and `app/` subfolders; required entries exist |
109
- | `module-service-getters` | a `…Module`'s public getters return only `new X(...)` of a class from its own `./app/`, named `x` (camelCase) |
109
+ | `module-shape` | `…Module` = `@HttpModule` + `static readonly services`, `…MessageHandlers` = `@MessageHandlers` + `static readonly handlers`, `…Workers` = `@Workers` + `static readonly workers`; entries are classes from the module's own `./app/`; static methods with a return type are config providers; nothing else (no context, fields, getters, setters) |
110
+ | `module-service-getters` | (legacy, not in `configs.ddd`) a hand-wired `…Module`'s public getters return only `new X(...)` of a class from its own `./app/`, named `x` (camelCase) |
111
+ | `unique-class-names` | a class name is declared once under `src/modules/**` + `src/common/**` — class names key the wiring and the route registry |
112
+ | `subclass-declares-constructor` | app and infrastructure classes that `extends` something declare their own constructor (`ignoreBases` for `RepositoryBase` & co.) |
110
113
  | `port-file` | ports live in `app/ports/<Name>Port.ts`, one exported interface per file named like it; only types; no `…Port` elsewhere |
111
- | `port-has-adapters` | every `XRepositoryPort` has at least one implementation in the module's infrastructure |
114
+ | `port-has-adapters` | every `XPort` in `app/ports/` resolves to exactly one adapter per storage profile the way the container does: `implements` anywhere under `src/modules/**` / `src/common/**` (a prefixed `…XRepository` counts for repository ports), `pg` vs `memory` storage, a composite taking `XPort[]` wins, `@Adapter({ profile })` adapters are left to the profile |
112
115
  | `test-location` | `<TestedFile>.<optional-suffix>.test.ts` sits next to `<TestedFile>.ts`; no `__tests__/` |
113
116
 
114
117
  ### Cross-cutting
115
118
 
116
119
  | Rule | What it checks |
117
120
  |---|---|
121
+ | `no-manual-wiring` | no `new X(...)` of an app class (`…Service/View/Handler` from an `app/` path), an adapter (`infrastructure/` path, `Pg…`, `InMemory…`), a module/group class or an application-provided infra class (`JetStreamMessagePublisher`, …) — outside `domain/`, `testing/`, `deployments/`, tests |
122
+ | `config-provider-only` | `config.pick/pickMaybe/has` only in static config methods of a `…Module`/`…MessageHandlers`/`…Workers` class, under `common/config/` or `deployments/` (`allow`, `moduleStaticMethods`) |
118
123
  | `throw-app-error` | only `throw AppError.x(...)` / `throw new AppError(...)` from `@pjts/core`; rethrowing the caught error is allowed |
119
124
  | `import-only-in` | a package is imported only under given path fragments (`uuid` → `/domain/`) |
120
125
  | `no-duplicate-sdk-types` | frontend: no local type named like one in the generated client's `types.d.ts` |
package/dist/index.js CHANGED
@@ -20,6 +20,11 @@ const import_only_in_1 = tslib_1.__importDefault(require("./rules/import-only-in
20
20
  const knex_first_1 = tslib_1.__importDefault(require("./rules/knex-first"));
21
21
  const module_layout_1 = tslib_1.__importDefault(require("./rules/module-layout"));
22
22
  const module_service_getters_1 = tslib_1.__importDefault(require("./rules/module-service-getters"));
23
+ const module_shape_1 = tslib_1.__importDefault(require("./rules/module-shape"));
24
+ const no_manual_wiring_1 = tslib_1.__importDefault(require("./rules/no-manual-wiring"));
25
+ const config_provider_only_1 = tslib_1.__importDefault(require("./rules/config-provider-only"));
26
+ const unique_class_names_1 = tslib_1.__importDefault(require("./rules/unique-class-names"));
27
+ const subclass_declares_constructor_1 = tslib_1.__importDefault(require("./rules/subclass-declares-constructor"));
23
28
  const no_async_in_domain_1 = tslib_1.__importDefault(require("./rules/no-async-in-domain"));
24
29
  const no_duplicate_sdk_types_1 = tslib_1.__importDefault(require("./rules/no-duplicate-sdk-types"));
25
30
  const no_entity_assembly_in_app_1 = tslib_1.__importDefault(require("./rules/no-entity-assembly-in-app"));
@@ -53,6 +58,11 @@ const rules = {
53
58
  'knex-first': knex_first_1.default,
54
59
  'module-layout': module_layout_1.default,
55
60
  'module-service-getters': module_service_getters_1.default,
61
+ 'module-shape': module_shape_1.default,
62
+ 'no-manual-wiring': no_manual_wiring_1.default,
63
+ 'config-provider-only': config_provider_only_1.default,
64
+ 'unique-class-names': unique_class_names_1.default,
65
+ 'subclass-declares-constructor': subclass_declares_constructor_1.default,
56
66
  'no-async-in-domain': no_async_in_domain_1.default,
57
67
  'no-duplicate-sdk-types': no_duplicate_sdk_types_1.default,
58
68
  'no-entity-assembly-in-app': no_entity_assembly_in_app_1.default,
@@ -106,6 +116,10 @@ const createDddConfig = (options = {}) => {
106
116
  // Only …Pg…Repository classes depend on the client, and only they write through it.
107
117
  'pjts/db-client-dependency': 'error',
108
118
  'pjts/db-writes-in-repositories': 'error',
119
+ // Environment is read in module static config methods and common/config/ only.
120
+ 'pjts/config-provider-only': 'error',
121
+ // Class names key the generated wiring and the route registry.
122
+ 'pjts/unique-class-names': 'error',
109
123
  // Every thrown error is an AppError (rethrowing a caught error unchanged is fine).
110
124
  'pjts/throw-app-error': 'error',
111
125
  // Identities are minted by the domain.
@@ -119,6 +133,12 @@ const createDddConfig = (options = {}) => {
119
133
  ...(authAccess ? { 'pjts/auth-access': ['error', authAccess] } : {}),
120
134
  },
121
135
  },
136
+ {
137
+ // Nobody builds app classes, adapters or modules by hand: the IoC container does, from the wiring.
138
+ files: [`${src}/**/*.ts`],
139
+ ignores: [...exclude, `${module}/domain/**`, `${module}/testing/**`, `${src}/testing/**`],
140
+ rules: { 'pjts/no-manual-wiring': 'error' },
141
+ },
122
142
  // ── Messages: one per file, MessageNames in step ──────────────────────────
123
143
  {
124
144
  files: [`${messages}/*.ts`],
@@ -132,17 +152,18 @@ const createDddConfig = (options = {}) => {
132
152
  folders: ['app', 'domain', 'infrastructure', 'testing'],
133
153
  subfolders: { app: ['dto', 'ports'] },
134
154
  required: ['app', 'index.ts'],
135
- // The module's MessageHandlerBase composition root sits next to its HTTP module.
136
- rootFiles: ['{Module}Module.ts', '{Module}MessageHandlers.ts', 'index.ts'],
155
+ // The module's handler and worker groups sit next to its HTTP module.
156
+ rootFiles: ['{Module}Module.ts', '{Module}MessageHandlers.ts', '{Module}Workers.ts', 'index.ts'],
137
157
  }],
138
158
  // Ports: app/ports/<Name>Port.ts, one exported interface named like the file; `…Port` nowhere else.
139
159
  'pjts/port-file': 'error',
140
160
  },
141
161
  },
142
162
  {
143
- // Modules expose their own app-layer classes — and nothing else — as camelCase getters.
144
- files: [`${module}/*Module.ts`],
145
- rules: { 'pjts/module-service-getters': ['error', { suffixes: ['Service', 'View', 'Handler'] }] },
163
+ // Modules and groups are declarations: @HttpModule + static services, @MessageHandlers + static
164
+ // handlers, @Workers + static workers, static config methods — no context, getters or setters.
165
+ files: [`${module}/*Module.ts`, `${module}/*MessageHandlers.ts`, `${module}/*Workers.ts`],
166
+ rules: { 'pjts/module-shape': 'error' },
146
167
  },
147
168
  // ── Domain layer: pure, synchronous, no I/O ───────────────────────────────
148
169
  {
@@ -177,7 +198,8 @@ const createDddConfig = (options = {}) => {
177
198
  files: [`${module}/app/*.ts`],
178
199
  ignores: ['**/index.ts'],
179
200
  rules: {
180
- 'pjts/app-class-suffix': ['error', { allowed: ['Service', 'Handler', 'View'] }],
201
+ // App layer = services (incl. @AppService views), message handlers, workers. Providers live in infrastructure.
202
+ 'pjts/app-class-suffix': ['error', { allowed: ['Service', 'Handler', 'Worker', 'View'] }],
181
203
  'pjts/return-entities': 'error',
182
204
  'pjts/no-entity-assembly-in-app': 'error',
183
205
  'pjts/find-one-naming': 'error',
@@ -192,6 +214,11 @@ const createDddConfig = (options = {}) => {
192
214
  files: [`${module}/app/ports/*.ts`],
193
215
  rules: { 'pjts/port-has-adapters': 'error' },
194
216
  },
217
+ {
218
+ // Subclasses declare the dependencies they take; the wiring is derived from constructors.
219
+ files: [`${module}/app/*.ts`, `${module}/infrastructure/**/*.ts`],
220
+ rules: { 'pjts/subclass-declares-constructor': ['error', { ignoreBases: ['RepositoryBase', 'TransactionalRepositoryBase', 'OutboxRepository', 'KnexViewBase'] }] },
221
+ },
195
222
  {
196
223
  files: [`${module}/app/**/*.ts`, `${module}/infrastructure/**/*.ts`],
197
224
  rules: { 'pjts/save-contract': 'error' },
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /** `<…>/src/<rest>` → the `src` directory of the file being linted, or null. */
2
+ export declare const srcRoot: (context: any) => string | null;
3
+ export interface ScannedClass {
4
+ name: string;
5
+ file: string;
6
+ implements: Set<string>;
7
+ /** `pg`, `memory`, `pg-nats`, … from the folder, else from the `Pg`/`InMemory` prefix. */
8
+ storage?: string;
9
+ /** `@Adapter({ profile: 'x' })` */
10
+ profile?: string;
11
+ /** Constructor parameter types written as `T[]` / `Array<T>`. */
12
+ arrayParams: Set<string>;
13
+ }
14
+ /**
15
+ * Every class declared under `<src>/modules/**` and `<src>/common/**` (tests excluded), read once per
16
+ * lint run with regexes — enough for names, `implements`, storage, profile and array constructor params.
17
+ */
18
+ export declare const scanClasses: (src: string) => ScannedClass[];
19
+ /** Test hook: forget scanned trees so a test can add files and re-scan. */
20
+ export declare const resetScans: () => void;
21
+ /** Adapters of `port` that the container would consider under `storage` with no active profile. */
22
+ export declare const candidatesOf: (classes: ScannedClass[], port: string, storage: string) => ScannedClass[];
23
+ export declare const isCompositeOf: (cls: ScannedClass, port: string) => boolean;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isCompositeOf = exports.candidatesOf = exports.resetScans = exports.scanClasses = exports.srcRoot = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
6
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
7
+ const ast_1 = require("./ast");
8
+ /** `<…>/src/<rest>` → the `src` directory of the file being linted, or null. */
9
+ const srcRoot = (context) => {
10
+ const file = (0, ast_1.filePath)(context);
11
+ const index = file.lastIndexOf('/src/');
12
+ return index === -1 ? null : file.slice(0, index + 4);
13
+ };
14
+ exports.srcRoot = srcRoot;
15
+ const STORAGE_FOLDERS = { pg: 'pg', 'pg+nats': 'pg-nats', 'pg-nats': 'pg-nats', 'in-memory': 'memory', memory: 'memory' };
16
+ const storageOf = (file, name) => {
17
+ const segments = file.split('/');
18
+ const infrastructure = segments.indexOf('infrastructure');
19
+ if (infrastructure !== -1) {
20
+ for (const segment of segments.slice(infrastructure + 1, -1)) {
21
+ if (STORAGE_FOLDERS[segment])
22
+ return STORAGE_FOLDERS[segment];
23
+ }
24
+ }
25
+ if (/^InMemory[A-Z]/.test(name))
26
+ return 'memory';
27
+ if (/^Pg[A-Z]/.test(name))
28
+ return 'pg';
29
+ return undefined;
30
+ };
31
+ const scans = new Map();
32
+ /**
33
+ * Every class declared under `<src>/modules/**` and `<src>/common/**` (tests excluded), read once per
34
+ * lint run with regexes — enough for names, `implements`, storage, profile and array constructor params.
35
+ */
36
+ const scanClasses = (src) => {
37
+ const cached = scans.get(src);
38
+ if (cached)
39
+ return cached;
40
+ const classes = [];
41
+ const walk = (current) => {
42
+ if (!node_fs_1.default.existsSync(current))
43
+ return;
44
+ for (const entry of node_fs_1.default.readdirSync(current, { withFileTypes: true })) {
45
+ const full = node_path_1.default.join(current, entry.name);
46
+ if (entry.isDirectory()) {
47
+ if (!/^(__tests?__|node_modules)$/.test(entry.name))
48
+ walk(full);
49
+ }
50
+ else if (/\.ts$/.test(entry.name) && !/\.(test|spec|d)\.ts$/.test(entry.name)) {
51
+ const source = node_fs_1.default.readFileSync(full, 'utf8');
52
+ const file = full.split(node_path_1.default.sep).join('/');
53
+ for (const match of source.matchAll(/(?:@Adapter\(\s*\{[^}]*profile\s*:\s*['"`]([\w-]+)['"`][^}]*\}\s*\)\s*)?(?:export\s+)?(?:abstract\s+)?class\s+(\w+)([^{]*)\{/g)) {
54
+ const [, profile, name, header] = match;
55
+ const implemented = header.match(/\bimplements\s+([\w\s,<>.]+)/)?.[1] ?? '';
56
+ const body = source.slice(match.index + match[0].length);
57
+ const constructorParams = body.match(/constructor\s*\(([^)]*)\)/)?.[1] ?? '';
58
+ const arrayParams = new Set();
59
+ for (const array of constructorParams.matchAll(/:\s*(?:readonly\s+)?(\w+)\[\]|:\s*(?:Readonly)?Array<\s*(\w+)\s*>/g)) {
60
+ arrayParams.add(array[1] ?? array[2]);
61
+ }
62
+ classes.push({
63
+ name,
64
+ file,
65
+ implements: new Set((implemented.match(/\b[A-Z]\w*/g) ?? []).filter((word) => word !== 'implements')),
66
+ storage: storageOf(file, name),
67
+ profile,
68
+ arrayParams,
69
+ });
70
+ }
71
+ }
72
+ }
73
+ };
74
+ walk(node_path_1.default.join(src, 'modules'));
75
+ walk(node_path_1.default.join(src, 'common'));
76
+ scans.set(src, classes);
77
+ return classes;
78
+ };
79
+ exports.scanClasses = scanClasses;
80
+ /** Test hook: forget scanned trees so a test can add files and re-scan. */
81
+ const resetScans = () => scans.clear();
82
+ exports.resetScans = resetScans;
83
+ const isMemory = (storage) => storage === 'memory';
84
+ /** Adapters of `port` that the container would consider under `storage` with no active profile. */
85
+ const candidatesOf = (classes, port, storage) => {
86
+ const base = port.replace(/Port$/, '');
87
+ return classes.filter((cls) => (cls.implements.has(port) || (/RepositoryPort$/.test(port) && cls.name !== base && cls.name.endsWith(base))) &&
88
+ (cls.storage === undefined || isMemory(cls.storage) === isMemory(storage)) &&
89
+ cls.profile === undefined);
90
+ };
91
+ exports.candidatesOf = candidatesOf;
92
+ const isCompositeOf = (cls, port) => cls.implements.has(port) && cls.arrayParams.has(port);
93
+ exports.isCompositeOf = isCompositeOf;
94
+ //# sourceMappingURL=wiring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wiring.js","sourceRoot":"","sources":["../../src/lib/wiring.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Environment is read in exactly two kinds of places: static config methods of a module class
3
+ * (`static calendarFeedConfig(): CalendarFeedConfig`) and the shared `common/config/` providers (plus
4
+ * the entry file under `deployments/`). Everywhere else a class declares the `…Config` object it needs
5
+ * as a constructor parameter.
6
+ */
7
+ declare const _default: import("eslint").Rule.RuleModule;
8
+ export default _default;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ast_1 = require("../lib/ast");
4
+ const rule_1 = require("../lib/rule");
5
+ /**
6
+ * Environment is read in exactly two kinds of places: static config methods of a module class
7
+ * (`static calendarFeedConfig(): CalendarFeedConfig`) and the shared `common/config/` providers (plus
8
+ * the entry file under `deployments/`). Everywhere else a class declares the `…Config` object it needs
9
+ * as a constructor parameter.
10
+ */
11
+ exports.default = (0, rule_1.defineRule)({
12
+ meta: {
13
+ type: 'suggestion',
14
+ docs: { description: 'config.pick / pickMaybe / has only in config providers' },
15
+ messages: {
16
+ outside: '`{{object}}.{{method}}(...)` is allowed only in {{where}} — declare the `…Config` object as a constructor dependency instead.',
17
+ },
18
+ schema: [{
19
+ type: 'object',
20
+ properties: {
21
+ configNames: { type: 'array', items: { type: 'string' } },
22
+ methods: { type: 'array', items: { type: 'string' } },
23
+ allow: { type: 'array', items: { type: 'string' } },
24
+ moduleStaticMethods: { type: 'boolean' },
25
+ },
26
+ additionalProperties: false,
27
+ }],
28
+ },
29
+ create(context) {
30
+ const configNames = context.options[0]?.configNames ?? ['config'];
31
+ const methods = context.options[0]?.methods ?? ['pick', 'pickMaybe', 'has'];
32
+ const allow = context.options[0]?.allow ?? ['/common/config/', '/deployments/'];
33
+ const moduleStaticMethods = context.options[0]?.moduleStaticMethods ?? true;
34
+ const file = (0, ast_1.filePath)(context);
35
+ if (allow.some((fragment) => file.includes(fragment)))
36
+ return {};
37
+ const where = [moduleStaticMethods ? 'static config methods of a module class' : null, ...allow.map((fragment) => fragment.replace(/^\//, ''))]
38
+ .filter(Boolean)
39
+ .join(', ');
40
+ const inModuleStaticMethod = (node) => {
41
+ const ancestors = context.sourceCode.getAncestors(node);
42
+ const method = ancestors.find((ancestor) => ancestor.type === 'MethodDefinition');
43
+ const cls = ancestors.find((ancestor) => ancestor.type === 'ClassDeclaration');
44
+ return !!method && method.static && method.kind === 'method' && /(Module|MessageHandlers|Workers)$/.test(cls?.id?.name ?? '');
45
+ };
46
+ return {
47
+ 'CallExpression[callee.type="MemberExpression"][callee.object.type="Identifier"]'(node) {
48
+ const object = node.callee.object.name;
49
+ const method = node.callee.property?.name;
50
+ if (!configNames.includes(object) || !methods.includes(method))
51
+ return;
52
+ if (moduleStaticMethods && inModuleStaticMethod(node))
53
+ return;
54
+ context.report({ node, messageId: 'outside', data: { object, method, where } });
55
+ },
56
+ };
57
+ },
58
+ });
59
+ //# sourceMappingURL=config-provider-only.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-provider-only.js","sourceRoot":"","sources":["../../src/rules/config-provider-only.ts"],"names":[],"mappings":";;AAAA,oCAAsC;AACtC,sCAAyC;AAEzC;;;;;GAKG;AACH,kBAAe,IAAA,iBAAU,EAAC;IACxB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,EAAE,WAAW,EAAE,wDAAwD,EAAE;QAC/E,QAAQ,EAAE;YACR,OAAO,EAAE,+HAA+H;SACzI;QACD,MAAM,EAAE,CAAC;gBACP,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBACzD,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBACrD,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBACnD,mBAAmB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;iBACzC;gBACD,oBAAoB,EAAE,KAAK;aAC5B,CAAC;KACH;IACD,MAAM,CAAC,OAAO;QACZ,MAAM,WAAW,GAAa,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5E,MAAM,OAAO,GAAa,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QACtF,MAAM,KAAK,GAAa,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;QAC1F,MAAM,mBAAmB,GAAY,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,mBAAmB,IAAI,IAAI,CAAC;QACrF,MAAM,IAAI,GAAG,IAAA,cAAQ,EAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QACjE,MAAM,KAAK,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,yCAAyC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;aAC5I,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAW,EAAE;YAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAU,CAAC;YACjE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;YAClF,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;YAC/E,OAAO,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,mCAAmC,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QAChI,CAAC,CAAC;QAEF,OAAO;YACL,iFAAiF,CAAC,IAAI;gBACpF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC;gBAC1C,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,OAAO;gBACvE,IAAI,mBAAmB,IAAI,oBAAoB,CAAC,IAAI,CAAC;oBAAE,OAAO;gBAC9D,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YAClF,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -1,19 +1,2 @@
1
- /**
2
- * A module class exposes application-layer classes — and only those — through public getters named
3
- * after them in camelCase:
4
- *
5
- * import { ServiceOfferPublicView } from './app/ServiceOfferPublicView';
6
- *
7
- * public get serviceOfferPublicView() {
8
- * return new ServiceOfferPublicView(this.serviceOfferRepo);
9
- * }
10
- *
11
- * Two directions are checked:
12
- * - every public getter returns `new X(...)` where X is a value imported from the module's own
13
- * `./app/…` (not `./app/dto` or `./app/ports`), and is named X with a lower-case first letter;
14
- * - every `new X(...)` of an app use-case class (suffix `Service` | `View` | `Handler`) sits in a public,
15
- * non-static getter. Internal app helpers (notifiers, runners) may be built in the constructor for
16
- * wiring — they just can't be exposed.
17
- */
18
1
  declare const _default: import("eslint").Rule.RuleModule;
19
2
  export default _default;
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const fs_1 = tslib_1.__importDefault(require("fs"));
5
+ const path_1 = tslib_1.__importDefault(require("path"));
3
6
  const rule_1 = require("../lib/rule");
4
7
  const ast_1 = require("../lib/ast");
5
8
  /**
@@ -15,10 +18,35 @@ const ast_1 = require("../lib/ast");
15
18
  * Two directions are checked:
16
19
  * - every public getter returns `new X(...)` where X is a value imported from the module's own
17
20
  * `./app/…` (not `./app/dto` or `./app/ports`), and is named X with a lower-case first letter;
18
- * - every `new X(...)` of an app use-case class (suffix `Service` | `View` | `Handler`) sits in a public,
19
- * non-static getter. Internal app helpers (notifiers, runners) may be built in the constructor for
20
- * wiring — they just can't be exposed.
21
+ * - every `new X(...)` of an endpoint class — one decorated `@AppService` (`endpointDecorators`) in the
22
+ * module's `app/` — sits in a public, non-static getter. Other app classes (collaborator services,
23
+ * workers) are built privately in the constructor and passed to the endpoints that need them.
21
24
  */
25
+ /** module `app/` dir → names of the classes decorated as endpoints there (per lint run). */
26
+ const endpointClasses = new Map();
27
+ const endpointsIn = (appDir, decorators) => {
28
+ const key = `${appDir}#${decorators.join(',')}`;
29
+ if (!endpointClasses.has(key)) {
30
+ const names = new Set();
31
+ const pattern = new RegExp(`@(?:${decorators.join('|')})(?:\\([^)]*\\))?\\s+export\\s+(?:default\\s+)?class\\s+(\\w+)`, 'g');
32
+ const walk = (dir) => {
33
+ if (!fs_1.default.existsSync(dir))
34
+ return;
35
+ for (const entry of fs_1.default.readdirSync(dir, { withFileTypes: true })) {
36
+ const full = path_1.default.join(dir, entry.name);
37
+ if (entry.isDirectory())
38
+ walk(full);
39
+ else if (/\.ts$/.test(entry.name) && !/\.test\.ts$/.test(entry.name)) {
40
+ for (const match of fs_1.default.readFileSync(full, 'utf8').matchAll(pattern))
41
+ names.add(match[1]);
42
+ }
43
+ }
44
+ };
45
+ walk(appDir);
46
+ endpointClasses.set(key, names);
47
+ }
48
+ return endpointClasses.get(key);
49
+ };
22
50
  exports.default = (0, rule_1.defineRule)({
23
51
  meta: {
24
52
  type: 'suggestion',
@@ -31,12 +59,17 @@ exports.default = (0, rule_1.defineRule)({
31
59
  },
32
60
  schema: [{
33
61
  type: 'object',
34
- properties: { suffixes: { type: 'array', items: { type: 'string' }, minItems: 1 } },
62
+ properties: {
63
+ suffixes: { type: 'array', items: { type: 'string' }, minItems: 1 },
64
+ endpointDecorators: { type: 'array', items: { type: 'string' }, minItems: 1 },
65
+ },
35
66
  additionalProperties: false,
36
67
  }],
37
68
  },
38
69
  create(context) {
39
70
  const suffixes = context.options[0]?.suffixes ?? ['Service', 'View', 'Handler'];
71
+ const endpointDecorators = context.options[0]?.endpointDecorators ?? ['AppService'];
72
+ const appDir = path_1.default.join(path_1.default.dirname(context.filename), 'app');
40
73
  /** local name → import source, for value imports of the file. */
41
74
  const imports = new Map();
42
75
  const isAppSource = (source) => /^\.\/app(\/|$)/.test(source) && !/^\.\/app\/(dto|ports)(\/|$)/.test(source);
@@ -110,11 +143,14 @@ exports.default = (0, rule_1.defineRule)({
110
143
  }
111
144
  }
112
145
  },
113
- // App use-case classes: only constructed inside public getters.
146
+ // Endpoint classes: only constructed inside public getters.
114
147
  'NewExpression[callee.type="Identifier"]'(node) {
115
148
  const name = node.callee.name;
116
149
  if (!isAppClass(name) || !suffixes.some((suffix) => name.endsWith(suffix)))
117
150
  return;
151
+ // Only endpoints must be exposed; collaborator services and workers are private wiring.
152
+ if (!endpointsIn(appDir, endpointDecorators).has(name))
153
+ return;
118
154
  const ancestors = context.sourceCode.getAncestors(node);
119
155
  const member = (0, ast_1.findLast)(ancestors, (a) => a.type === 'MethodDefinition' || a.type === 'PropertyDefinition');
120
156
  if (!member || !isModuleClass(member.parent.parent))
@@ -1 +1 @@
1
- {"version":3,"file":"module-service-getters.js","sourceRoot":"","sources":["../../src/rules/module-service-getters.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"module-service-getters.js","sourceRoot":"","sources":["../../src/rules/module-service-getters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Module, message-handler and worker group classes are declarations, not factories:
3
+ *
4
+ * @HttpModule('/v1')
5
+ * export class CalendarModule {
6
+ * static readonly services = [CalendarEventService, CalendarView]
7
+ * static calendarFeedConfig(): CalendarFeedConfig { … } // config provider (optional)
8
+ * }
9
+ *
10
+ * - `…Module` carries `@HttpModule` and `static readonly services`; `…MessageHandlers` carries
11
+ * `@MessageHandlers` and `static readonly handlers`; `…Workers` carries `@Workers` and `static readonly workers`;
12
+ * - every list entry is a class imported from the module's own `./app/…` (not `./app/dto`, `./app/ports`);
13
+ * - nothing else: no constructor, fields, getters, setters or instance methods (that was manual wiring);
14
+ * static methods with an explicit return type are config providers and are allowed unless
15
+ * `configProviders: false`.
16
+ */
17
+ declare const _default: import("eslint").Rule.RuleModule;
18
+ export default _default;
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ast_1 = require("../lib/ast");
4
+ const rule_1 = require("../lib/rule");
5
+ /**
6
+ * Module, message-handler and worker group classes are declarations, not factories:
7
+ *
8
+ * @HttpModule('/v1')
9
+ * export class CalendarModule {
10
+ * static readonly services = [CalendarEventService, CalendarView]
11
+ * static calendarFeedConfig(): CalendarFeedConfig { … } // config provider (optional)
12
+ * }
13
+ *
14
+ * - `…Module` carries `@HttpModule` and `static readonly services`; `…MessageHandlers` carries
15
+ * `@MessageHandlers` and `static readonly handlers`; `…Workers` carries `@Workers` and `static readonly workers`;
16
+ * - every list entry is a class imported from the module's own `./app/…` (not `./app/dto`, `./app/ports`);
17
+ * - nothing else: no constructor, fields, getters, setters or instance methods (that was manual wiring);
18
+ * static methods with an explicit return type are config providers and are allowed unless
19
+ * `configProviders: false`.
20
+ */
21
+ exports.default = (0, rule_1.defineRule)({
22
+ meta: {
23
+ type: 'suggestion',
24
+ docs: { description: 'Module and group classes declare their services, handlers or workers statically and nothing else' },
25
+ messages: {
26
+ decorator: '{{name}} must be decorated with @{{decorator}}.',
27
+ list: '{{name}} must declare `static readonly {{key}} = [...]` as an array literal of class names.',
28
+ notApp: '"{{entry}}" in {{name}}.{{key}} must be a class imported from ./app/ — {{what}}.',
29
+ member: '{{name}} may only declare `static readonly {{key}}`{{extra}}; found {{what}}. Wiring is derived by the container.',
30
+ configReturn: 'Static method {{name}}.{{method}}() must declare the config type it returns.',
31
+ },
32
+ schema: [{
33
+ type: 'object',
34
+ properties: { configProviders: { type: 'boolean' } },
35
+ additionalProperties: false,
36
+ }],
37
+ },
38
+ create(context) {
39
+ const configProviders = context.options[0]?.configProviders ?? true;
40
+ const imports = new Map();
41
+ const isAppSource = (source) => /^\.\/app(\/|$)/.test(source) && !/^\.\/app\/(dto|ports)(\/|$)/.test(source);
42
+ const kinds = [
43
+ { suffix: /Module$/, decorator: 'HttpModule', key: 'services' },
44
+ { suffix: /MessageHandlers$/, decorator: 'MessageHandlers', key: 'handlers' },
45
+ { suffix: /Workers$/, decorator: 'Workers', key: 'workers' },
46
+ ];
47
+ const describe = (member) => {
48
+ if (member.type === 'MethodDefinition') {
49
+ if (member.kind === 'constructor')
50
+ return 'a constructor';
51
+ if (member.kind === 'get' || member.kind === 'set')
52
+ return `${member.kind}ter \`${(0, ast_1.memberName)(member)}\``;
53
+ return `${member.static ? 'static ' : ''}method \`${(0, ast_1.memberName)(member)}\``;
54
+ }
55
+ return `${member.static ? 'static ' : ''}field \`${(0, ast_1.memberName)(member)}\``;
56
+ };
57
+ return {
58
+ ImportDeclaration(node) {
59
+ if (node.importKind === 'type')
60
+ return;
61
+ for (const specifier of node.specifiers) {
62
+ if (specifier.importKind !== 'type')
63
+ imports.set(specifier.local.name, node.source.value);
64
+ }
65
+ },
66
+ ClassDeclaration(node) {
67
+ const name = node.id?.name;
68
+ const kind = name && kinds.find((candidate) => candidate.suffix.test(name));
69
+ if (!kind)
70
+ return;
71
+ const extra = configProviders ? ' and static config methods' : '';
72
+ if (!(0, ast_1.decoratorNames)(node).includes(kind.decorator)) {
73
+ context.report({ node: node.id, messageId: 'decorator', data: { name, decorator: kind.decorator } });
74
+ }
75
+ const list = node.body.body.find((member) => member.type === 'PropertyDefinition' && member.static && (0, ast_1.memberName)(member) === kind.key);
76
+ if (!list || list.value?.type !== 'ArrayExpression') {
77
+ context.report({ node: list ?? node.id, messageId: 'list', data: { name, key: kind.key } });
78
+ }
79
+ else {
80
+ for (const element of list.value.elements) {
81
+ if (element?.type !== 'Identifier') {
82
+ context.report({ node: element ?? list, messageId: 'notApp', data: { entry: element ? context.sourceCode.getText(element) : 'hole', name, key: kind.key, what: 'it is not a class name' } });
83
+ continue;
84
+ }
85
+ const source = imports.get(element.name);
86
+ if (!source || !isAppSource(source)) {
87
+ context.report({
88
+ node: element,
89
+ messageId: 'notApp',
90
+ data: { entry: element.name, name, key: kind.key, what: source ? `it comes from '${source}'` : 'it is not imported from ./app/' },
91
+ });
92
+ }
93
+ }
94
+ }
95
+ for (const member of node.body.body) {
96
+ if (member === list)
97
+ continue;
98
+ const isStaticMethod = member.type === 'MethodDefinition' && member.static && member.kind === 'method';
99
+ if (configProviders && isStaticMethod) {
100
+ if (!member.value.returnType) {
101
+ context.report({ node: member.key, messageId: 'configReturn', data: { name, method: (0, ast_1.memberName)(member) } });
102
+ }
103
+ continue;
104
+ }
105
+ context.report({ node: member.key ?? member, messageId: 'member', data: { name, key: kind.key, extra, what: describe(member) } });
106
+ }
107
+ },
108
+ };
109
+ },
110
+ });
111
+ //# sourceMappingURL=module-shape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-shape.js","sourceRoot":"","sources":["../../src/rules/module-shape.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Nobody constructs application classes, adapters or modules by hand — the IoC container does, from the
3
+ * generated wiring. `new X(...)` is reported when X is:
4
+ * - a value imported from an `app/` path (not `app/dto`, `app/ports`) whose name ends with a use-case suffix;
5
+ * - a value imported from an `infrastructure` path, or named `Pg…` / `InMemory…`;
6
+ * - a class named `…Module`, `…MessageHandlers` or `…Workers`;
7
+ * - one of the infrastructure classes the application itself provides (`JetStreamMessagePublisher`, …).
8
+ * Apply it outside `domain/`, `testing/`, `deployments/` and tests.
9
+ */
10
+ declare const _default: import("eslint").Rule.RuleModule;
11
+ export default _default;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const rule_1 = require("../lib/rule");
4
+ /**
5
+ * Nobody constructs application classes, adapters or modules by hand — the IoC container does, from the
6
+ * generated wiring. `new X(...)` is reported when X is:
7
+ * - a value imported from an `app/` path (not `app/dto`, `app/ports`) whose name ends with a use-case suffix;
8
+ * - a value imported from an `infrastructure` path, or named `Pg…` / `InMemory…`;
9
+ * - a class named `…Module`, `…MessageHandlers` or `…Workers`;
10
+ * - one of the infrastructure classes the application itself provides (`JetStreamMessagePublisher`, …).
11
+ * Apply it outside `domain/`, `testing/`, `deployments/` and tests.
12
+ */
13
+ exports.default = (0, rule_1.defineRule)({
14
+ meta: {
15
+ type: 'suggestion',
16
+ docs: { description: 'No hand-built application classes, adapters or modules — the container builds them' },
17
+ messages: {
18
+ wiring: '`new {{name}}(...)` is manual wiring ({{why}}): declare {{name}} as a constructor dependency and let the container build it.',
19
+ },
20
+ schema: [{
21
+ type: 'object',
22
+ properties: {
23
+ suffixes: { type: 'array', items: { type: 'string' } },
24
+ infraClasses: { type: 'array', items: { type: 'string' } },
25
+ },
26
+ additionalProperties: false,
27
+ }],
28
+ },
29
+ create(context) {
30
+ const suffixes = context.options[0]?.suffixes ?? ['Service', 'View', 'Handler'];
31
+ const infraClasses = context.options[0]?.infraClasses ?? ['JetStreamMessagePublisher', 'JetStreamMessageSubscriber', 'RedisMessageDeduplicator', 'MessageRepeater'];
32
+ const imports = new Map();
33
+ const isApp = (source) => /(^|\/)app(\/|$)/.test(source) && !/(^|\/)app\/(dto|ports)(\/|$)/.test(source);
34
+ const isInfrastructure = (source) => /(^|\/)infrastructure(\/|$)/.test(source);
35
+ const why = (name) => {
36
+ const source = imports.get(name);
37
+ if (/(Module|MessageHandlers|Workers)$/.test(name))
38
+ return 'module and group classes are declarations';
39
+ if (source && isApp(source) && suffixes.some((suffix) => name.endsWith(suffix)))
40
+ return `${name} is an application class from '${source}'`;
41
+ if (source && isInfrastructure(source))
42
+ return `${name} is an adapter from '${source}'`;
43
+ if (/^(Pg|InMemory)[A-Z]/.test(name))
44
+ return `${name} is an adapter`;
45
+ if (infraClasses.includes(name))
46
+ return `${name} is provided by the application`;
47
+ return null;
48
+ };
49
+ return {
50
+ ImportDeclaration(node) {
51
+ if (node.importKind === 'type')
52
+ return;
53
+ for (const specifier of node.specifiers) {
54
+ if (specifier.importKind !== 'type')
55
+ imports.set(specifier.local.name, node.source.value);
56
+ }
57
+ },
58
+ 'NewExpression[callee.type="Identifier"]'(node) {
59
+ const name = node.callee.name;
60
+ const reason = why(name);
61
+ if (reason)
62
+ context.report({ node, messageId: 'wiring', data: { name, why: reason } });
63
+ },
64
+ };
65
+ },
66
+ });
67
+ //# sourceMappingURL=no-manual-wiring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-manual-wiring.js","sourceRoot":"","sources":["../../src/rules/no-manual-wiring.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  /**
2
- * Every `<X>RepositoryPort` declared in `app/ports/` has at least one implementation in the module's
3
- * `infrastructure/`: a class that `implements` the port, or a prefixed `…<X>Repository`
4
- * (`PgXRepository`, `PgNatsXRepository`, `InMemoryXRepository`, …). Which prefix is right for its
5
- * folder is `repository-naming`'s job.
2
+ * Every `<X>Port` declared in `app/ports/` resolves to exactly one adapter per storage profile, the
3
+ * way the IoC container resolves it: a class anywhere under `src/modules/**` or `src/common/**` that
4
+ * `implements` the port (for repository ports a prefixed `…<X>Repository` also counts), filtered by
5
+ * storage (`pg` vs `memory` folders / prefixes), with a composite (`implements T`, takes `T[]`)
6
+ * winning over the adapters it wraps, and adapters behind `@Adapter({ profile })` left to the profile.
6
7
  * Reads sibling files, so editors only re-check it when the port file itself is re-linted.
7
8
  */
8
9
  declare const _default: import("eslint").Rule.RuleModule;
@@ -1,60 +1,59 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
5
- const node_path_1 = tslib_1.__importDefault(require("node:path"));
6
3
  const ast_1 = require("../lib/ast");
7
4
  const rule_1 = require("../lib/rule");
8
- /** infrastructure dir → [{ name, implements: Set<string> }] for every class declared in it (per lint run). */
9
- const infrastructureClasses = new Map();
10
- const classesIn = (dir) => {
11
- if (!infrastructureClasses.has(dir)) {
12
- const classes = [];
13
- const walk = (current) => {
14
- if (!node_fs_1.default.existsSync(current))
15
- return;
16
- for (const entry of node_fs_1.default.readdirSync(current, { withFileTypes: true })) {
17
- const full = node_path_1.default.join(current, entry.name);
18
- if (entry.isDirectory())
19
- walk(full);
20
- else if (/\.ts$/.test(entry.name) && !/\.test\.ts$/.test(entry.name)) {
21
- for (const match of node_fs_1.default.readFileSync(full, 'utf8').matchAll(/\bclass\s+(\w+)([^{]*)\{/g)) {
22
- const implemented = match[2].match(/\bimplements\s+([\w\s,<>.]+)/)?.[1] ?? '';
23
- classes.push({ name: match[1], implements: new Set(implemented.match(/\w+/g) ?? []) });
24
- }
25
- }
26
- }
27
- };
28
- walk(dir);
29
- infrastructureClasses.set(dir, classes);
30
- }
31
- return infrastructureClasses.get(dir);
32
- };
5
+ const wiring_1 = require("../lib/wiring");
33
6
  /**
34
- * Every `<X>RepositoryPort` declared in `app/ports/` has at least one implementation in the module's
35
- * `infrastructure/`: a class that `implements` the port, or a prefixed `…<X>Repository`
36
- * (`PgXRepository`, `PgNatsXRepository`, `InMemoryXRepository`, …). Which prefix is right for its
37
- * folder is `repository-naming`'s job.
7
+ * Every `<X>Port` declared in `app/ports/` resolves to exactly one adapter per storage profile, the
8
+ * way the IoC container resolves it: a class anywhere under `src/modules/**` or `src/common/**` that
9
+ * `implements` the port (for repository ports a prefixed `…<X>Repository` also counts), filtered by
10
+ * storage (`pg` vs `memory` folders / prefixes), with a composite (`implements T`, takes `T[]`)
11
+ * winning over the adapters it wraps, and adapters behind `@Adapter({ profile })` left to the profile.
38
12
  * Reads sibling files, so editors only re-check it when the port file itself is re-linted.
39
13
  */
40
14
  exports.default = (0, rule_1.defineRule)({
41
15
  meta: {
42
16
  type: 'suggestion',
43
- docs: { description: 'Require every repository port to have at least one infrastructure implementation' },
44
- messages: { missing: 'Port "{{port}}" has no implementation in {{module}}/infrastructure/ (expected e.g. Pg{{base}}).' },
45
- schema: [],
17
+ docs: { description: 'Require every port to have exactly one adapter per storage profile' },
18
+ messages: {
19
+ missing: 'Port "{{port}}" has no adapter under src/modules or src/common (expected e.g. Pg{{base}} implementing it).',
20
+ ambiguous: 'Port "{{port}}" has {{count}} adapters in storage "{{storage}}": {{names}} — keep one, make one a composite taking {{port}}[], or mark them with @Adapter({ profile }).',
21
+ composites: 'Port "{{port}}" has more than one composite adapter: {{names}}.',
22
+ },
23
+ schema: [{
24
+ type: 'object',
25
+ properties: { storages: { type: 'array', items: { type: 'string' } } },
26
+ additionalProperties: false,
27
+ }],
46
28
  },
47
29
  create(context) {
30
+ const storages = context.options[0]?.storages ?? ['pg', 'memory'];
48
31
  const location = (0, ast_1.moduleLocation)(context);
49
- if (!location || location.rest[0] !== 'app' || location.rest[1] !== 'ports')
32
+ const src = (0, wiring_1.srcRoot)(context);
33
+ if (!location || !src || location.rest[0] !== 'app' || location.rest[1] !== 'ports')
50
34
  return {};
51
35
  return {
52
- 'TSInterfaceDeclaration[id.name=/RepositoryPort$/]'(node) {
36
+ 'TSInterfaceDeclaration[id.name=/Port$/]'(node) {
53
37
  const port = node.id.name;
54
38
  const base = port.replace(/Port$/, '');
55
- const implemented = classesIn(node_path_1.default.join(location.root, 'infrastructure')).some((cls) => cls.implements.has(port) || (cls.name !== base && cls.name.endsWith(base) && /^[A-Z]/.test(cls.name)));
56
- if (!implemented)
57
- context.report({ node: node.id, messageId: 'missing', data: { port, base, module: location.module } });
39
+ const classes = (0, wiring_1.scanClasses)(src);
40
+ const implementers = classes.filter((cls) => cls.implements.has(port) || (/RepositoryPort$/.test(port) && cls.name !== base && cls.name.endsWith(base)));
41
+ if (implementers.length === 0) {
42
+ context.report({ node: node.id, messageId: 'missing', data: { port, base } });
43
+ return;
44
+ }
45
+ for (const storage of storages) {
46
+ const candidates = (0, wiring_1.candidatesOf)(classes, port, storage);
47
+ const composites = candidates.filter((cls) => (0, wiring_1.isCompositeOf)(cls, port));
48
+ if (composites.length > 1) {
49
+ context.report({ node: node.id, messageId: 'composites', data: { port, names: composites.map((cls) => cls.name).join(', ') } });
50
+ return;
51
+ }
52
+ if (composites.length === 0 && candidates.length > 1) {
53
+ context.report({ node: node.id, messageId: 'ambiguous', data: { port, storage, count: String(candidates.length), names: candidates.map((cls) => cls.name).join(', ') } });
54
+ return;
55
+ }
56
+ }
58
57
  },
59
58
  };
60
59
  },
@@ -1 +1 @@
1
- {"version":3,"file":"port-has-adapters.js","sourceRoot":"","sources":["../../src/rules/port-has-adapters.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"port-has-adapters.js","sourceRoot":"","sources":["../../src/rules/port-has-adapters.ts"],"names":[],"mappings":";;AAAA,oCAA4C;AAC5C,sCAAyC;AACzC,0CAAkF;AAElF;;;;;;;GAOG;AACH,kBAAe,IAAA,iBAAU,EAAC;IACxB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,EAAE,WAAW,EAAE,oEAAoE,EAAE;QAC3F,QAAQ,EAAE;YACR,OAAO,EAAE,4GAA4G;YACrH,SAAS,EAAE,yKAAyK;YACpL,UAAU,EAAE,iEAAiE;SAC9E;QACD,MAAM,EAAE,CAAC;gBACP,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;gBACtE,oBAAoB,EAAE,KAAK;aAC5B,CAAC;KACH;IACD,MAAM,CAAC,OAAO;QACZ,MAAM,QAAQ,GAAa,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,IAAA,oBAAc,EAAC,OAAO,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,IAAA,gBAAO,EAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO;YAAE,OAAO,EAAE,CAAC;QAC/F,OAAO;YACL,yCAAyC,CAAC,IAAI;gBAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;gBAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACvC,MAAM,OAAO,GAAG,IAAA,oBAAW,EAAC,GAAG,CAAC,CAAC;gBACjC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACzJ,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC9B,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;oBAC9E,OAAO;gBACT,CAAC;gBACD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,MAAM,UAAU,GAAG,IAAA,qBAAY,EAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;oBACxD,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,sBAAa,EAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;oBACxE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC1B,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;wBAChI,OAAO;oBACT,CAAC;oBACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACrD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC1K,OAAO;oBACT,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Application services, adapters, handlers and workers that extend a class declare their own
3
+ * constructor: the wiring is derived from constructor signatures, and an inherited signature hides
4
+ * which dependencies the subclass really takes (and lets several subclasses share one ambiguous port).
5
+ */
6
+ declare const _default: import("eslint").Rule.RuleModule;
7
+ export default _default;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const rule_1 = require("../lib/rule");
4
+ /**
5
+ * Application services, adapters, handlers and workers that extend a class declare their own
6
+ * constructor: the wiring is derived from constructor signatures, and an inherited signature hides
7
+ * which dependencies the subclass really takes (and lets several subclasses share one ambiguous port).
8
+ */
9
+ exports.default = (0, rule_1.defineRule)({
10
+ meta: {
11
+ type: 'suggestion',
12
+ docs: { description: 'Subclasses in app/ and infrastructure/ declare their own constructor' },
13
+ messages: { missing: '{{name}} extends {{base}} but declares no constructor; declare the dependencies it takes (the wiring is derived from them).' },
14
+ schema: [{
15
+ type: 'object',
16
+ properties: { ignoreBases: { type: 'array', items: { type: 'string' } } },
17
+ additionalProperties: false,
18
+ }],
19
+ },
20
+ create(context) {
21
+ const ignoreBases = context.options[0]?.ignoreBases ?? [];
22
+ return {
23
+ 'ClassDeclaration[superClass]'(node) {
24
+ const base = context.sourceCode.getText(node.superClass).replace(/<.*$/, '');
25
+ if (ignoreBases.includes(base) || (node.abstract ?? false))
26
+ return;
27
+ const hasConstructor = node.body.body.some((member) => member.type === 'MethodDefinition' && member.kind === 'constructor');
28
+ if (!hasConstructor)
29
+ context.report({ node: node.id ?? node, messageId: 'missing', data: { name: node.id?.name ?? 'class', base } });
30
+ },
31
+ };
32
+ },
33
+ });
34
+ //# sourceMappingURL=subclass-declares-constructor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subclass-declares-constructor.js","sourceRoot":"","sources":["../../src/rules/subclass-declares-constructor.ts"],"names":[],"mappings":";;AAAA,sCAAyC;AAEzC;;;;GAIG;AACH,kBAAe,IAAA,iBAAU,EAAC;IACxB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,EAAE,WAAW,EAAE,sEAAsE,EAAE;QAC7F,QAAQ,EAAE,EAAE,OAAO,EAAE,6HAA6H,EAAE;QACpJ,MAAM,EAAE,CAAC;gBACP,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;gBACzE,oBAAoB,EAAE,KAAK;aAC5B,CAAC;KACH;IACD,MAAM,CAAC,OAAO;QACZ,MAAM,WAAW,GAAa,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,IAAI,EAAE,CAAC;QACpE,OAAO;YACL,8BAA8B,CAAC,IAAI;gBACjC,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAC7E,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC;oBAAE,OAAO;gBACnE,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;gBAC5H,IAAI,CAAC,cAAc;oBAAE,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,IAAI,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;YACvI,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Class names are the keys of the generated wiring and of the HTTP route registry, so they are unique
3
+ * per repository (ubiquitous language). Reads every class declared under `src/modules/**` and
4
+ * `src/common/**` once per lint run.
5
+ */
6
+ declare const _default: import("eslint").Rule.RuleModule;
7
+ export default _default;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
5
+ const ast_1 = require("../lib/ast");
6
+ const rule_1 = require("../lib/rule");
7
+ const wiring_1 = require("../lib/wiring");
8
+ /**
9
+ * Class names are the keys of the generated wiring and of the HTTP route registry, so they are unique
10
+ * per repository (ubiquitous language). Reads every class declared under `src/modules/**` and
11
+ * `src/common/**` once per lint run.
12
+ */
13
+ exports.default = (0, rule_1.defineRule)({
14
+ meta: {
15
+ type: 'problem',
16
+ docs: { description: 'Class names are unique across the repository' },
17
+ messages: { duplicate: 'Class "{{name}}" is also declared in {{other}}; class names must be unique per repository.' },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ const src = (0, wiring_1.srcRoot)(context);
22
+ if (!src)
23
+ return {};
24
+ const file = (0, ast_1.filePath)(context);
25
+ return {
26
+ ClassDeclaration(node) {
27
+ if (!node.id)
28
+ return;
29
+ const other = (0, wiring_1.scanClasses)(src).find((cls) => cls.name === node.id.name && cls.file !== file);
30
+ if (other)
31
+ context.report({ node: node.id, messageId: 'duplicate', data: { name: node.id.name, other: node_path_1.default.relative(src, other.file) } });
32
+ },
33
+ };
34
+ },
35
+ });
36
+ //# sourceMappingURL=unique-class-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unique-class-names.js","sourceRoot":"","sources":["../../src/rules/unique-class-names.ts"],"names":[],"mappings":";;;AAAA,kEAA6B;AAC7B,oCAAsC;AACtC,sCAAyC;AACzC,0CAAqD;AAErD;;;;GAIG;AACH,kBAAe,IAAA,iBAAU,EAAC;IACxB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,EAAE,WAAW,EAAE,8CAA8C,EAAE;QACrE,QAAQ,EAAE,EAAE,SAAS,EAAE,4FAA4F,EAAE;QACrH,MAAM,EAAE,EAAE;KACX;IACD,MAAM,CAAC,OAAO;QACZ,MAAM,GAAG,GAAG,IAAA,gBAAO,EAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,IAAA,cAAQ,EAAC,OAAO,CAAC,CAAC;QAC/B,OAAO;YACL,gBAAgB,CAAC,IAAI;gBACnB,IAAI,CAAC,IAAI,CAAC,EAAE;oBAAE,OAAO;gBACrB,MAAM,KAAK,GAAG,IAAA,oBAAW,EAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;gBAC7F,IAAI,KAAK;oBAAE,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,mBAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5I,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pjts/eslint-style-rules",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Piotr Józefów DDD utility package — ESLint rules and flat-config preset enforcing the pjts DDD layout and conventions",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",