@ddd-ts-kit/eslint-plugin 0.10.0 → 0.11.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.
package/README.md CHANGED
@@ -142,6 +142,8 @@ is an error whatever the configured limit). `strict` sets every rule to `error`.
142
142
  | [`ports/value-import`](docs/rules/ports-value-import.md) | `ddd-ts-kit/ports-value-import` | a port named in a dependency list or given to `bind` is not a type-only import; fixable | `error` | custom |
143
143
  | [`scheduling/job-triggers-use-case`](docs/rules/scheduling-job-triggers-use-case.md) | `ddd-ts-kit/scheduling-job-triggers-use-case` | a job lives in `application/scheduling/*.job.ts`, implements `ScheduledJob`, sends a command, and touches neither a repository nor the model | `error` | custom |
144
144
  | [`scheduling/job-name`](docs/rules/scheduling-job-name.md) | `ddd-ts-kit/scheduling-job-name` | a job is named `<context>.<job-name>` by a string literal, and its `systemActor` carries that name | `error` | custom |
145
+ | [`lifecycle/status-through-machine`](docs/rules/lifecycle-status-through-machine.md) | `ddd-ts-kit/lifecycle-status-through-machine` | in an aggregate that imports its state machine, the status is written only from the machine (`next`, `start`) or copied from a status already read | `error` | custom |
146
+ | [`process/sends-commands-only`](docs/rules/process-sends-commands-only.md) | `ddd-ts-kit/process-sends-commands-only` | a process manager of `application/processes/` imports no aggregate, entity, repository, domain service, port or infrastructure: it changes the world through the commands it decides | `error` | custom |
145
147
  | [`imports/alias-only`](docs/rules/imports-alias-only.md) | `ddd-ts-kit/imports-alias-only` | a file of the project is imported by its alias (`@/...`, `$test/...`, `$scripts/...`), never by a relative path, the same directory included; no `.` or `..` segment in an alias path; fixable | `error` | custom |
146
148
  | [`imports/extension`](docs/rules/imports-extension.md) | `ddd-ts-kit/imports-extension` | an import of a file of the project ends as `importExtension` of the config says: no extension under `none`, `.js` under `js`; fixable | `error` | custom |
147
149
 
@@ -0,0 +1,3 @@
1
+ import { type TSESLint } from '@typescript-eslint/utils';
2
+ export declare const lifecycleStatusThroughMachine: TSESLint.RuleModule<"notThroughMachine", [], import("../index.js").RuleDocs, TSESLint.RuleListener>;
3
+ //# sourceMappingURL=lifecycle-status-through-machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle-status-through-machine.d.ts","sourceRoot":"","sources":["../../src/rules/lifecycle-status-through-machine.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,QAAQ,EAAiB,MAAM,0BAA0B,CAAC;AAYlG,eAAO,MAAM,6BAA6B,qGAgDxC,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { AST_NODE_TYPES, ASTUtils } from '@typescript-eslint/utils';
2
+ import { className } from '../support/classes/class-name.js';
3
+ import { enclosingMember } from '../support/classes/enclosing-member.js';
4
+ import { defineRule } from '../support/rule/define-rule.js';
5
+ const STATUS = 'status';
6
+ const MACHINE_FILE = /(?:^|\/)state-machines\/[^/]+\.state-machine(?:\.[cm]?[jt]s)?$/;
7
+ const THROUGH = new Set(['next', 'start']);
8
+ export const lifecycleStatusThroughMachine = defineRule({
9
+ id: 'lifecycle/status-through-machine',
10
+ type: 'problem',
11
+ recommended: 'error',
12
+ description: 'In an aggregate that imports its state machine, the status is written only from the machine (`machine.next(...)`, `machine.start(...)`) or copied from a status already read.',
13
+ messages: {
14
+ notThroughMachine: "{{className}} writes its status without its state machine ({{value}}). Ask the machine: `status: {{machine}}.next(this.state.status, '<transition>')`, so that a forbidden transition is refused in one place.",
15
+ },
16
+ create({ file, sourceCode, report }) {
17
+ if (!isAggregateFile(file)) {
18
+ return {};
19
+ }
20
+ const machines = new Set();
21
+ const judge = (node, value) => {
22
+ const site = enclosingMember(node);
23
+ const machine = [...machines][0];
24
+ if (site === undefined || machine === undefined || isThroughMachine(value, { machines, sourceCode })) {
25
+ return;
26
+ }
27
+ const data = { className: className(site.body.parent), value: sourceCode.getText(value), machine };
28
+ report({ node: value, messageId: 'notThroughMachine', data });
29
+ };
30
+ return {
31
+ ImportDeclaration(node) {
32
+ if (MACHINE_FILE.test(node.source.value)) {
33
+ node.specifiers.forEach((specifier) => machines.add(specifier.local.name));
34
+ }
35
+ },
36
+ Property(node) {
37
+ if (node.parent.type === AST_NODE_TYPES.ObjectExpression && keyIsStatus(node.key)) {
38
+ judge(node, node.value);
39
+ }
40
+ },
41
+ AssignmentExpression(node) {
42
+ if (node.left.type === AST_NODE_TYPES.MemberExpression && keyIsStatus(node.left.property)) {
43
+ judge(node, node.right);
44
+ }
45
+ },
46
+ };
47
+ },
48
+ });
49
+ function isAggregateFile(file) {
50
+ const { location } = file;
51
+ return (location.area === 'context' && location.layer === 'domain' && !file.isTest && location.inside[0] === 'aggregates');
52
+ }
53
+ function keyIsStatus(key) {
54
+ return ((key.type === AST_NODE_TYPES.Identifier && key.name === STATUS) ||
55
+ (key.type === AST_NODE_TYPES.Literal && key.value === STATUS));
56
+ }
57
+ /**
58
+ * A call of the machine, or a status copied from one already read (`this.state.status`, a
59
+ * parameter named `status`, `const { status } = ...`). A local binding is followed back to its value:
60
+ * `const status = InvoiceStatus.Paid; this.state = { ...this.state, status }` is a write by hand.
61
+ */
62
+ function isThroughMachine(value, judged) {
63
+ if (value.type === AST_NODE_TYPES.Identifier) {
64
+ return isBoundThroughMachine(value, judged);
65
+ }
66
+ if (value.type === AST_NODE_TYPES.MemberExpression) {
67
+ return keyIsStatus(value.property);
68
+ }
69
+ return isMachineCall(value, judged.machines);
70
+ }
71
+ function isBoundThroughMachine(identifier, judged) {
72
+ const definition = ASTUtils.findVariable(judged.sourceCode.getScope(identifier), identifier.name)?.defs[0];
73
+ if (definition?.node.type !== AST_NODE_TYPES.VariableDeclarator) {
74
+ return definition !== undefined && identifier.name === STATUS;
75
+ }
76
+ const { id, init } = definition.node;
77
+ return id.type !== AST_NODE_TYPES.Identifier || (init !== null && isThroughMachine(init, judged));
78
+ }
79
+ function isMachineCall(value, machines) {
80
+ if (value.type !== AST_NODE_TYPES.CallExpression || value.callee.type !== AST_NODE_TYPES.MemberExpression) {
81
+ return false;
82
+ }
83
+ const { object, property } = value.callee;
84
+ return (object.type === AST_NODE_TYPES.Identifier &&
85
+ machines.has(object.name) &&
86
+ property.type === AST_NODE_TYPES.Identifier &&
87
+ THROUGH.has(property.name));
88
+ }
89
+ //# sourceMappingURL=lifecycle-status-through-machine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle-status-through-machine.js","sourceRoot":"","sources":["../../src/rules/lifecycle-status-through-machine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const processSendsCommandsOnly: import("@typescript-eslint/utils/ts-eslint").RuleModule<"writes", [], import("../index.js").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
2
+ //# sourceMappingURL=process-sends-commands-only.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-sends-commands-only.d.ts","sourceRoot":"","sources":["../../src/rules/process-sends-commands-only.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,wBAAwB,kKAuBnC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { defineRule } from '../support/rule/define-rule.js';
2
+ import { importListener } from '../support/imports/import-listener.js';
3
+ const WRITERS = {
4
+ domain: ['aggregates', 'entities', 'repositories', 'services'],
5
+ application: ['ports'],
6
+ };
7
+ export const processSendsCommandsOnly = defineRule({
8
+ id: 'process/sends-commands-only',
9
+ type: 'problem',
10
+ recommended: 'error',
11
+ description: 'A process manager of application/processes decides from its state and what happened, and changes the world only through the commands it sends: it imports no aggregate, entity, repository, domain service, port or infrastructure.',
12
+ messages: {
13
+ writes: 'This process imports {{target}}. A process never writes an aggregate, of its context or another, nor calls an outside system: it answers a decision whose commands do it, each authorized and transactional in its own handler. Remove the import and send a command instead.',
14
+ },
15
+ create({ file, report }) {
16
+ if (!isProcessFile(file)) {
17
+ return {};
18
+ }
19
+ return importListener(file, ({ node, target }) => {
20
+ const reached = reachedWriter(target);
21
+ if (reached !== undefined) {
22
+ report({ node, messageId: 'writes', data: { target: reached } });
23
+ }
24
+ });
25
+ },
26
+ });
27
+ function isProcessFile(file) {
28
+ const { location } = file;
29
+ return (!file.isTest &&
30
+ location.area === 'context' &&
31
+ location.layer === 'application' &&
32
+ location.inside[0] === 'processes' &&
33
+ file.path.endsWith('.process.ts'));
34
+ }
35
+ function reachedWriter(target) {
36
+ if (target.kind !== 'file' || target.location.area !== 'context') {
37
+ return undefined;
38
+ }
39
+ const { layer, inside } = target.location;
40
+ if (layer === 'infrastructure') {
41
+ return 'infrastructure/';
42
+ }
43
+ const [folder = ''] = inside;
44
+ return WRITERS[layer]?.includes(folder) === true ? `${layer}/${folder}/` : undefined;
45
+ }
46
+ //# sourceMappingURL=process-sends-commands-only.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-sends-commands-only.js","sourceRoot":"","sources":["../../src/rules/process-sends-commands-only.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAIvE,MAAM,OAAO,GAAgD;IAC3D,MAAM,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,CAAC;IAC9D,WAAW,EAAE,CAAC,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,UAAU,CAAY;IAC5D,EAAE,EAAE,6BAA6B;IACjC,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,OAAO;IACpB,WAAW,EACT,qOAAqO;IACvO,QAAQ,EAAE;QACR,MAAM,EACJ,+QAA+Q;KAClR;IACD,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;QACrB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,cAAc,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;YAC/C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;YAEtC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,aAAa,CAAC,IAAgB;IACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAE1B,OAAO,CACL,CAAC,IAAI,CAAC,MAAM;QACZ,QAAQ,CAAC,IAAI,KAAK,SAAS;QAC3B,QAAQ,CAAC,KAAK,KAAK,aAAa;QAChC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,WAAW;QAClC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAClC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,MAAoB;IACzC,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACjE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;IAE1C,IAAI,KAAK,KAAK,gBAAgB,EAAE,CAAC;QAC/B,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC;IAE7B,OAAO,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACvF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/rules/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAkIlE,+HAA+H;AAC/H,eAAO,MAAM,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEnD,CAAC"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/rules/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAsIlE,+HAA+H;AAC/H,eAAO,MAAM,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEnD,CAAC"}
@@ -50,6 +50,8 @@ import { presentationControllerDelegates } from './presentation-controller-deleg
50
50
  import { presentationControllerShape } from './presentation-controller-shape.js';
51
51
  import { presentationGuardAtTheEdge } from './presentation-guard-at-the-edge.js';
52
52
  import { purityNoAmbientRandomness, purityNoEnvironment, purityNoSystemClock } from './purity.js';
53
+ import { lifecycleStatusThroughMachine } from './lifecycle-status-through-machine.js';
54
+ import { processSendsCommandsOnly } from './process-sends-commands-only.js';
53
55
  import { schedulingJobName } from './scheduling-job-name.js';
54
56
  import { schedulingJobTriggersUseCase } from './scheduling-job-triggers-use-case.js';
55
57
  import { standardNoParallelInterface } from './standard-no-parallel-interface.js';
@@ -115,6 +117,8 @@ const ALL = [
115
117
  portsNoConcreteDependency,
116
118
  portsValueImport,
117
119
  schedulingJobTriggersUseCase,
120
+ lifecycleStatusThroughMachine,
121
+ processSendsCommandsOnly,
118
122
  schedulingJobName,
119
123
  importsAliasOnly,
120
124
  importsExtension,
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/rules/rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/rules/rules.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.10.0";
1
+ export declare const VERSION = "0.11.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.10.0';
1
+ export const VERSION = '0.11.0';
2
2
  //# sourceMappingURL=version.js.map
@@ -0,0 +1,69 @@
1
+ # ddd-ts-kit/lifecycle-status-through-machine
2
+
3
+ Architecture id: `lifecycle/status-through-machine`. Default severity: `error` in `recommended`, `error` in `strict`.
4
+
5
+ Applies to: `domain/aggregates/*` of a context, specs aside, when the file imports a state machine
6
+ of `domain/state-machines/`.
7
+
8
+ ## Why
9
+
10
+ A state machine says once which status follows which, and what refuses a forbidden transition.
11
+ An aggregate that also writes its status by hand keeps a second, silent copy of the lifecycle:
12
+ the diagram generated from the machine then lies, and a transition the machine forbids happens
13
+ anyway. The status is therefore only ever written from the machine, or copied from a status
14
+ already read.
15
+
16
+ ## Reported
17
+
18
+ In an aggregate file that imports a `*.state-machine` module, inside a member of a class:
19
+
20
+ - an object property `status: <value>` whose value is not a call `<machine>.next(..)` or
21
+ `<machine>.start(..)` of an imported machine, a status read from somewhere (`this.state.status`,
22
+ `state.status`) or the variable `status`
23
+ - an assignment `<target>.status = <value>`, by the same test
24
+
25
+ Incorrect:
26
+
27
+ ```ts
28
+ confirm(now: Date): void {
29
+ if (this.state.status !== 'requested') {
30
+ throw AppointmentError.alreadyConfirmed(this.id);
31
+ }
32
+
33
+ this.state = { ...this.state, changedAt: now, status: 'booked' };
34
+ }
35
+ ```
36
+
37
+ Correct:
38
+
39
+ ```ts
40
+ confirm(now: Date): void {
41
+ this.state = { ...this.state, changedAt: now, status: appointmentLifecycle.next(this.state.status, 'confirm') };
42
+ }
43
+ ```
44
+
45
+ ## Details
46
+
47
+ The machine is any binding imported from a module whose path ends with
48
+ `state-machines/<name>.state-machine`. What the machine guarantees: `defineStateMachine` of
49
+ `@ddd-ts-kit/kernel`.
50
+
51
+ ## Options
52
+
53
+ None.
54
+
55
+ `rules."lifecycle/status-through-machine"` in `ddd-ts-kit.config.json` set to `off` silences the
56
+ rule, and `// ddd-ts-kit-disable-next-line lifecycle/status-through-machine -- <reason>` silences
57
+ one line, exactly as for `ddd-ts-kit check`.
58
+
59
+ ## Limits
60
+
61
+ - One file at a time: an aggregate whose state machine exists and is not imported is reported
62
+ by `ddd-ts-kit check` alone.
63
+ - A status written through a helper function, or held in a field initializer of the class, is
64
+ not followed.
65
+
66
+ ## With the CLI checker
67
+
68
+ `ddd-ts-kit check` reports the same id from the text of the files, and also an aggregate whose
69
+ state machine exists (`domain/state-machines/<aggregate>.state-machine.ts`) and is not imported.
@@ -0,0 +1,63 @@
1
+ # ddd-ts-kit/process-sends-commands-only
2
+
3
+ Architecture id: `process/sends-commands-only`. Default severity: `error` in `recommended`, `error` in `strict`.
4
+
5
+ Applies to: `application/processes/*.process.ts` of a context, specs aside.
6
+
7
+ ## Why
8
+
9
+ A process manager coordinates a long-running process: it reacts to events, keeps a state of its
10
+ own and decides what happens next. When it also loads and saves aggregates, it becomes a use case
11
+ nobody can send, with no permission, no audit and a transaction that spans what it should only
12
+ coordinate; when it writes the aggregate of another context, the boundary is gone. Its steps
13
+ answer a decision, and the commands of that decision do the work, each in its own handler.
14
+
15
+ ## Reported
16
+
17
+ An import, in a process file, of:
18
+
19
+ - `domain/aggregates/`, `domain/entities/`, `domain/repositories/` or `domain/services/` of any
20
+ context
21
+ - `application/ports/` of any context
22
+ - `infrastructure/` of any context
23
+
24
+ Incorrect:
25
+
26
+ ```ts
27
+ import { ReminderRepository } from '@/contexts/notification/domain/repositories/reminder.repository';
28
+
29
+ export class AppointmentReminderProcess { /* saves reminders itself */ }
30
+ ```
31
+
32
+ Correct:
33
+
34
+ ```ts
35
+ import { PlanReminderCommand } from '@/contexts/notification/application/commands/plan-reminder/plan-reminder.command';
36
+
37
+ export class AppointmentReminderProcess implements ProcessManager<ReminderProcessState> {
38
+ booked(event: AppointmentBookedV1, current: ReminderProcessState | undefined): ProcessDecision<ReminderProcessState> | undefined {
39
+ return { state: { appointmentId: event.payload.appointmentId, stage: 'waiting' }, commands: [new PlanReminderCommand(/* ... */)] };
40
+ }
41
+ }
42
+ ```
43
+
44
+ ## Details
45
+
46
+ Commands, the published language of upstream contexts, value objects, vocabularies and the
47
+ kernel stay allowed: a process builds commands and reads events.
48
+
49
+ ## Options
50
+
51
+ None.
52
+
53
+ `rules."process/sends-commands-only"` in `ddd-ts-kit.config.json` set to `off` silences the rule,
54
+ and `// ddd-ts-kit-disable-next-line process/sends-commands-only -- <reason>` silences one line,
55
+ exactly as for `ddd-ts-kit check`.
56
+
57
+ ## Limits
58
+
59
+ - An import read by a dynamic expression is not followed.
60
+
61
+ ## With the CLI checker
62
+
63
+ `ddd-ts-kit check` reports the same id from the text of the files.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ddd-ts-kit/eslint-plugin",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "AST-accurate ESLint rules for DDD and Clean Architecture in TypeScript: layer and context isolation, domain purity, clean code ordering.",
5
5
  "license": "MIT",
6
6
  "repository": {