@ddd-ts-kit/eslint-plugin 0.5.0 → 0.7.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.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -1
  3. package/dist/presets/create-ddd-ts-kit.d.ts.map +1 -1
  4. package/dist/presets/create-ddd-ts-kit.js +6 -1
  5. package/dist/presets/create-ddd-ts-kit.js.map +1 -1
  6. package/dist/project/config.d.ts +8 -0
  7. package/dist/project/config.d.ts.map +1 -1
  8. package/dist/project/parse-config.d.ts.map +1 -1
  9. package/dist/project/parse-config.js +9 -0
  10. package/dist/project/parse-config.js.map +1 -1
  11. package/dist/rules/clean-no-magic-number.d.ts +6 -0
  12. package/dist/rules/clean-no-magic-number.d.ts.map +1 -0
  13. package/dist/rules/clean-no-magic-number.js +99 -0
  14. package/dist/rules/clean-no-magic-number.js.map +1 -0
  15. package/dist/rules/declarations-role-declared.d.ts.map +1 -1
  16. package/dist/rules/declarations-role-declared.js +31 -9
  17. package/dist/rules/declarations-role-declared.js.map +1 -1
  18. package/dist/rules/events-name-format.d.ts.map +1 -1
  19. package/dist/rules/events-name-format.js +7 -1
  20. package/dist/rules/events-name-format.js.map +1 -1
  21. package/dist/rules/language-declared-vocabulary.d.ts +2 -0
  22. package/dist/rules/language-declared-vocabulary.d.ts.map +1 -0
  23. package/dist/rules/language-declared-vocabulary.js +70 -0
  24. package/dist/rules/language-declared-vocabulary.js.map +1 -0
  25. package/dist/rules/rules.d.ts.map +1 -1
  26. package/dist/rules/rules.js +4 -0
  27. package/dist/rules/rules.js.map +1 -1
  28. package/dist/support/classes/class-finder.d.ts.map +1 -1
  29. package/dist/support/classes/class-finder.js +2 -9
  30. package/dist/support/classes/class-finder.js.map +1 -1
  31. package/dist/support/parse/parse-source.d.ts +9 -0
  32. package/dist/support/parse/parse-source.d.ts.map +1 -0
  33. package/dist/support/parse/parse-source.js +21 -0
  34. package/dist/support/parse/parse-source.js.map +1 -0
  35. package/dist/support/vocabularies/declared-value.d.ts +14 -0
  36. package/dist/support/vocabularies/declared-value.d.ts.map +1 -0
  37. package/dist/support/vocabularies/declared-value.js +2 -0
  38. package/dist/support/vocabularies/declared-value.js.map +1 -0
  39. package/dist/support/vocabularies/project-vocabularies.d.ts +12 -0
  40. package/dist/support/vocabularies/project-vocabularies.d.ts.map +1 -0
  41. package/dist/support/vocabularies/project-vocabularies.js +47 -0
  42. package/dist/support/vocabularies/project-vocabularies.js.map +1 -0
  43. package/dist/support/vocabularies/values-declared-in.d.ts +16 -0
  44. package/dist/support/vocabularies/values-declared-in.d.ts.map +1 -0
  45. package/dist/support/vocabularies/values-declared-in.js +108 -0
  46. package/dist/support/vocabularies/values-declared-in.js.map +1 -0
  47. package/dist/version.d.ts +1 -1
  48. package/dist/version.js +1 -1
  49. package/docs/rules/clean-no-magic-number.md +59 -0
  50. package/docs/rules/declarations-role-declared.md +3 -3
  51. package/docs/rules/events-name-format.md +8 -4
  52. package/docs/rules/language-declared-vocabulary.md +64 -0
  53. package/package.json +1 -1
@@ -49,6 +49,8 @@ import { schedulingJobName } from './scheduling-job-name.js';
49
49
  import { schedulingJobTriggersUseCase } from './scheduling-job-triggers-use-case.js';
50
50
  import { standardNoParallelInterface } from './standard-no-parallel-interface.js';
51
51
  import { testNoMocks } from './test-no-mocks.js';
52
+ import { cleanNoMagicNumber } from './clean-no-magic-number.js';
53
+ import { languageDeclaredVocabulary } from './language-declared-vocabulary.js';
52
54
  import { tracingPlatformOnly } from './tracing-platform-only.js';
53
55
  const ALL = [
54
56
  layerDomainPurity,
@@ -58,6 +60,7 @@ const ALL = [
58
60
  contextPublishedLanguageOnly,
59
61
  contextDeclaredRelationship,
60
62
  contextPublishedLanguageIsAContract,
63
+ languageDeclaredVocabulary,
61
64
  purityNoSystemClock,
62
65
  purityNoAmbientRandomness,
63
66
  purityNoEnvironment,
@@ -71,6 +74,7 @@ const ALL = [
71
74
  cleanNoHashPrivate,
72
75
  cleanOneExportPerFile,
73
76
  cleanFileSize,
77
+ cleanNoMagicNumber,
74
78
  domainAggregateEncapsulation,
75
79
  domainValueObjectImmutability,
76
80
  domainNoGenericError,
@@ -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":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,iCAAiC,EAAE,MAAM,2CAA2C,CAAC;AAC9F,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EACL,2BAA2B,EAC3B,mCAAmC,EACnC,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,gCAAgC,EAAE,MAAM,yCAAyC,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AACrF,OAAO,EAAE,qCAAqC,EAAE,MAAM,gDAAgD,CAAC;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AACtF,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,iCAAiC,EAAE,iCAAiC,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,+BAA+B,EAAE,MAAM,wCAAwC,CAAC;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,uCAAuC,CAAC;AACrF,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,MAAM,GAAG,GAAG;IACV,iBAAiB;IACjB,sBAAsB;IACtB,iCAAiC;IACjC,iCAAiC;IACjC,4BAA4B;IAC5B,2BAA2B;IAC3B,mCAAmC;IACnC,0BAA0B;IAC1B,mBAAmB;IACnB,yBAAyB;IACzB,mBAAmB;IACnB,aAAa;IACb,iBAAiB;IACjB,oBAAoB;IACpB,mBAAmB;IACnB,uBAAuB;IACvB,mBAAmB;IACnB,kBAAkB;IAClB,kBAAkB;IAClB,qBAAqB;IACrB,aAAa;IACb,kBAAkB;IAClB,4BAA4B;IAC5B,6BAA6B;IAC7B,oBAAoB;IACpB,oBAAoB;IACpB,0BAA0B;IAC1B,iBAAiB;IACjB,uBAAuB;IACvB,iCAAiC;IACjC,4BAA4B;IAC5B,qCAAqC;IACrC,WAAW;IACX,gBAAgB;IAChB,oBAAoB;IACpB,wBAAwB;IACxB,kBAAkB;IAClB,aAAa;IACb,kBAAkB;IAClB,kBAAkB;IAClB,gBAAgB;IAChB,mBAAmB;IACnB,2BAA2B;IAC3B,2BAA2B;IAC3B,wBAAwB;IACxB,gCAAgC;IAChC,kBAAkB;IAClB,2BAA2B;IAC3B,oBAAoB;IACpB,yBAAyB;IACzB,gBAAgB;IAChB,4BAA4B;IAC5B,iBAAiB;IACjB,gBAAgB;IAChB,gBAAgB;IAChB,2BAA2B;IAC3B,+BAA+B;IAC/B,0BAA0B;CAC3B,CAAC;AAEF,+HAA+H;AAC/H,MAAM,CAAC,MAAM,KAAK,GAAsC,MAAM,CAAC,WAAW,CACxE,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAC7C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"class-finder.d.ts","sourceRoot":"","sources":["../../../src/support/classes/class-finder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGxF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAG/D,KAAK,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;AAEzC,kGAAkG;AAClG,UAAU,SAAS;IACjB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,gBAAgB,CAAC;CAC1C;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;AAgBlE;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAoBhH"}
1
+ {"version":3,"file":"class-finder.d.ts","sourceRoot":"","sources":["../../../src/support/classes/class-finder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAExF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAI/D,KAAK,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;AAEzC,kGAAkG;AAClG,UAAU,SAAS;IACjB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,gBAAgB,CAAC;CAC1C;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;AAclE;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAoBhH"}
@@ -2,9 +2,8 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { AST_NODE_TYPES } from '@typescript-eslint/utils';
4
4
  import { resolveImport } from '../../project/resolve-import.js';
5
- import { isRecord } from '../../project/is-record.js';
5
+ import { parseSource } from '../parse/parse-source.js';
6
6
  import { topLevelClasses } from './top-level-classes.js';
7
- const PARSER_OPTIONS = { sourceType: 'module', ecmaVersion: 'latest', range: true, loc: true };
8
7
  const sources = new Map();
9
8
  /**
10
9
  * Finds the class behind a name of the linted file: declared at its top, or imported by name
@@ -61,16 +60,10 @@ function readProgram(absolute, parser) {
61
60
  }
62
61
  function parseFile(absolute, parser) {
63
62
  try {
64
- const text = fs.readFileSync(absolute, 'utf8');
65
- const options = { ...PARSER_OPTIONS, filePath: absolute };
66
- const parsed = 'parseForESLint' in parser ? parser.parseForESLint(text, options).ast : parser.parse(text, options);
67
- return isProgram(parsed) ? parsed : undefined;
63
+ return parseSource(fs.readFileSync(absolute, 'utf8'), absolute, parser);
68
64
  }
69
65
  catch {
70
66
  return undefined;
71
67
  }
72
68
  }
73
- function isProgram(value) {
74
- return isRecord(value) && value['type'] === AST_NODE_TYPES.Program && Array.isArray(value['body']);
75
- }
76
69
  //# sourceMappingURL=class-finder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"class-finder.js","sourceRoot":"","sources":["../../../src/support/classes/class-finder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"class-finder.js","sourceRoot":"","sources":["../../../src/support/classes/class-finder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type TSESLint, type TSESTree } from '@typescript-eslint/utils';
2
+ type Parser = TSESLint.FlatConfig.Parser;
3
+ /**
4
+ * A source of the project other than the linted file, parsed with the parser of the run and
5
+ * nothing else (no types, no scope); undefined when the parser refuses it.
6
+ */
7
+ export declare function parseSource(text: string, filePath: string, parser: Parser): TSESTree.Program | undefined;
8
+ export {};
9
+ //# sourceMappingURL=parse-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-source.d.ts","sourceRoot":"","sources":["../../../src/support/parse/parse-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGxF,KAAK,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;AAIzC;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,OAAO,GAAG,SAAS,CAWxG"}
@@ -0,0 +1,21 @@
1
+ import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
+ import { isRecord } from '../../project/is-record.js';
3
+ const PARSER_OPTIONS = { sourceType: 'module', ecmaVersion: 'latest', range: true, loc: true };
4
+ /**
5
+ * A source of the project other than the linted file, parsed with the parser of the run and
6
+ * nothing else (no types, no scope); undefined when the parser refuses it.
7
+ */
8
+ export function parseSource(text, filePath, parser) {
9
+ try {
10
+ const options = { ...PARSER_OPTIONS, filePath };
11
+ const parsed = 'parseForESLint' in parser ? parser.parseForESLint(text, options).ast : parser.parse(text, options);
12
+ return isProgram(parsed) ? parsed : undefined;
13
+ }
14
+ catch {
15
+ return undefined;
16
+ }
17
+ }
18
+ function isProgram(value) {
19
+ return isRecord(value) && value['type'] === AST_NODE_TYPES.Program && Array.isArray(value['body']);
20
+ }
21
+ //# sourceMappingURL=parse-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-source.js","sourceRoot":"","sources":["../../../src/support/parse/parse-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAgC,MAAM,0BAA0B,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAItD,MAAM,cAAc,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AAE/F;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,QAAgB,EAAE,MAAc;IACxE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,GAAG,cAAc,EAAE,QAAQ,EAAE,CAAC;QAEhD,MAAM,MAAM,GACV,gBAAgB,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEtG,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,cAAc,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;AACrG,CAAC"}
@@ -0,0 +1,14 @@
1
+ /** A value of a closed vocabulary of the project, and how code reads it instead of the string. */
2
+ export interface DeclaredValue {
3
+ /** `AppointmentStatus.NoShow`, `billingPermissions['invoice.issue']`. */
4
+ readonly written: string;
5
+ /** The name of the vocabulary or of the permission set. */
6
+ readonly vocabulary: string;
7
+ /** The declaring file, relative to the project root. */
8
+ readonly file: string;
9
+ /** Who reads it: `everywhere` for a permission id; the context that declares it; or the platform, read by the platform and by the presentation of the contexts. */
10
+ readonly readBy: {
11
+ readonly context: string;
12
+ } | 'everywhere' | 'platform';
13
+ }
14
+ //# sourceMappingURL=declared-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declared-value.d.ts","sourceRoot":"","sources":["../../../src/support/vocabularies/declared-value.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,MAAM,WAAW,aAAa;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mKAAmK;IACnK,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,YAAY,GAAG,UAAU,CAAC;CAC3E"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=declared-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declared-value.js","sourceRoot":"","sources":["../../../src/support/vocabularies/declared-value.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import type { TSESLint } from '@typescript-eslint/utils';
2
+ import type { Project } from '../../project/linted-file.js';
3
+ import type { DeclaredValue } from './declared-value.js';
4
+ type Parser = TSESLint.FlatConfig.Parser;
5
+ /**
6
+ * The closed vocabularies the sources of the project declare, by value: the source root read on
7
+ * disk and parsed with the parser of the run, tests left out; a value two vocabularies share is
8
+ * listed under both. Without a parser, or for a file it cannot parse, nothing is declared.
9
+ */
10
+ export declare function projectVocabularies(project: Project, parser: Parser | undefined, now?: number): ReadonlyMap<string, readonly DeclaredValue[]>;
11
+ export {};
12
+ //# sourceMappingURL=project-vocabularies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-vocabularies.d.ts","sourceRoot":"","sources":["../../../src/support/vocabularies/project-vocabularies.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAG5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQzD,KAAK,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;AASzC;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,GAAG,SAAa,GACf,WAAW,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC,CAiB/C"}
@@ -0,0 +1,47 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { locate } from '../../project/locate.js';
4
+ import { parseSource } from '../parse/parse-source.js';
5
+ import { valuesDeclaredIn } from './values-declared-in.js';
6
+ /** How long a reading of the project is reused: a lint run reads it once, an editor sees a new value within seconds. */
7
+ const FRESH_FOR_MS = 5000;
8
+ const SKIPPED = new Set(['node_modules', 'dist', 'generated', 'test']);
9
+ const DECLARING = /as\s+const|definePermissions\(/;
10
+ const readings = new Map();
11
+ /**
12
+ * The closed vocabularies the sources of the project declare, by value: the source root read on
13
+ * disk and parsed with the parser of the run, tests left out; a value two vocabularies share is
14
+ * listed under both. Without a parser, or for a file it cannot parse, nothing is declared.
15
+ */
16
+ export function projectVocabularies(project, parser, now = Date.now()) {
17
+ const key = path.join(project.root, project.config.sourceRoot);
18
+ const known = readings.get(key);
19
+ if (known !== undefined && now >= known.at && now - known.at < FRESH_FOR_MS) {
20
+ return known.values;
21
+ }
22
+ const values = new Map();
23
+ for (const [value, declared] of sourcesUnder(key).flatMap((file) => declaredIn(project, file, parser))) {
24
+ values.set(value, [...(values.get(value) ?? []), declared]);
25
+ }
26
+ readings.set(key, { at: now, values });
27
+ return values;
28
+ }
29
+ function declaredIn(project, file, parser) {
30
+ const text = fs.readFileSync(file, 'utf8');
31
+ const program = DECLARING.test(text) && parser !== undefined ? parseSource(text, file, parser) : undefined;
32
+ const relative = path.relative(project.root, file).split(path.sep).join('/');
33
+ return program === undefined
34
+ ? []
35
+ : valuesDeclaredIn({ path: relative, location: locate(project.config, relative) }, program);
36
+ }
37
+ function sourcesUnder(directory) {
38
+ const entries = fs.existsSync(directory) ? fs.readdirSync(directory, { withFileTypes: true }) : [];
39
+ return entries.flatMap((entry) => {
40
+ const full = path.join(directory, entry.name);
41
+ if (entry.isDirectory()) {
42
+ return SKIPPED.has(entry.name) ? [] : sourcesUnder(full);
43
+ }
44
+ return /\.ts$/.test(entry.name) && !/\.(?:spec|test|d)\.ts$/.test(entry.name) ? [full] : [];
45
+ });
46
+ }
47
+ //# sourceMappingURL=project-vocabularies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-vocabularies.js","sourceRoot":"","sources":["../../../src/support/vocabularies/project-vocabularies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type TSESTree } from '@typescript-eslint/utils';
2
+ import type { Location } from '../../project/location.js';
3
+ import type { DeclaredValue } from './declared-value.js';
4
+ /** A source of the project: its path from the root, and where it stands. */
5
+ export interface Declaring {
6
+ readonly path: string;
7
+ readonly location: Location;
8
+ }
9
+ /**
10
+ * The values one parsed source declares: the entries of an exported object `as const` of string
11
+ * values next to the union type of the same name, `export type X = (typeof X)[keyof typeof X]`,
12
+ * comments, either quote and `satisfies` allowed; and the ids of a permission set
13
+ * (`definePermissions('billing', { 'invoice.issue': .. })` declares `billing:invoice.issue`).
14
+ */
15
+ export declare function valuesDeclaredIn(file: Declaring, program: TSESTree.Program): [string, DeclaredValue][];
16
+ //# sourceMappingURL=values-declared-in.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values-declared-in.d.ts","sourceRoot":"","sources":["../../../src/support/vocabularies/values-declared-in.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AASD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,CAkBtG"}
@@ -0,0 +1,108 @@
1
+ import { AST_NODE_TYPES } from '@typescript-eslint/utils';
2
+ const IDENTIFIER = /^[A-Za-z_$][\w$]*$/;
3
+ /**
4
+ * The values one parsed source declares: the entries of an exported object `as const` of string
5
+ * values next to the union type of the same name, `export type X = (typeof X)[keyof typeof X]`,
6
+ * comments, either quote and `satisfies` allowed; and the ids of a permission set
7
+ * (`definePermissions('billing', { 'invoice.issue': .. })` declares `billing:invoice.issue`).
8
+ */
9
+ export function valuesDeclaredIn(file, program) {
10
+ const unions = new Set(program.body.flatMap(unionTypeName));
11
+ return program.body.flatMap(exportedConstant).flatMap(({ name, init }) => {
12
+ if (unions.has(name)) {
13
+ const readBy = readerOf(file.location);
14
+ return objectEntries(asConstObject(init)).map(({ key, value }) => [
15
+ value,
16
+ { written: writtenAs(name, key), vocabulary: name, file: file.path, readBy },
17
+ ]);
18
+ }
19
+ return permissionIds(init).map(({ key, value }) => [
20
+ value,
21
+ { written: `${name}['${key}'].id`, vocabulary: name, file: file.path, readBy: 'everywhere' },
22
+ ]);
23
+ });
24
+ }
25
+ function exportedConstant(statement) {
26
+ const declaration = statement.type === AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : null;
27
+ if (declaration?.type !== AST_NODE_TYPES.VariableDeclaration || declaration.kind !== 'const') {
28
+ return [];
29
+ }
30
+ return declaration.declarations.flatMap(({ id, init }) => id.type === AST_NODE_TYPES.Identifier && init !== null ? [{ name: id.name, init }] : []);
31
+ }
32
+ /** `export type X = (typeof X)[keyof typeof X]`: the name of the vocabulary it closes. */
33
+ function unionTypeName(statement) {
34
+ const alias = statement.type === AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : null;
35
+ if (alias?.type !== AST_NODE_TYPES.TSTypeAliasDeclaration) {
36
+ return [];
37
+ }
38
+ const { typeAnnotation: type } = alias;
39
+ const name = alias.id.name;
40
+ const closes = type.type === AST_NODE_TYPES.TSIndexedAccessType &&
41
+ queries(type.objectType, name) &&
42
+ type.indexType.type === AST_NODE_TYPES.TSTypeOperator &&
43
+ type.indexType.operator === 'keyof' &&
44
+ type.indexType.typeAnnotation !== undefined &&
45
+ queries(type.indexType.typeAnnotation, name);
46
+ return closes ? [name] : [];
47
+ }
48
+ function queries(type, name) {
49
+ return (type.type === AST_NODE_TYPES.TSTypeQuery &&
50
+ type.exprName.type === AST_NODE_TYPES.Identifier &&
51
+ type.exprName.name === name);
52
+ }
53
+ /** `{ .. } as const`, or `{ .. } as const satisfies ..`. */
54
+ function asConstObject(init) {
55
+ const asserted = init.type === AST_NODE_TYPES.TSSatisfiesExpression ? init.expression : init;
56
+ const isConst = asserted.type === AST_NODE_TYPES.TSAsExpression &&
57
+ asserted.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference &&
58
+ asserted.typeAnnotation.typeName.type === AST_NODE_TYPES.Identifier &&
59
+ asserted.typeAnnotation.typeName.name === 'const';
60
+ return isConst && asserted.expression.type === AST_NODE_TYPES.ObjectExpression ? asserted.expression : undefined;
61
+ }
62
+ /** Every entry, or none when one of them is not a key with a string value: the object is then not a vocabulary. */
63
+ function objectEntries(object) {
64
+ const entries = (object?.properties ?? []).map(entryOf);
65
+ return entries.every((entry) => entry !== undefined) ? entries : [];
66
+ }
67
+ function entryOf(property) {
68
+ const key = property.type === AST_NODE_TYPES.Property && !property.computed ? keyOf(property.key) : undefined;
69
+ const value = property.type === AST_NODE_TYPES.Property ? stringOf(property.value) : undefined;
70
+ return key === undefined || value === undefined ? undefined : { key, value };
71
+ }
72
+ function permissionIds(init) {
73
+ const [context, permissions] = definesPermissions(init) ? init.arguments : [];
74
+ const prefix = context === undefined ? undefined : stringOf(context);
75
+ if (prefix === undefined || permissions?.type !== AST_NODE_TYPES.ObjectExpression) {
76
+ return [];
77
+ }
78
+ return permissions.properties.flatMap((property) => {
79
+ const key = property.type === AST_NODE_TYPES.Property ? keyOf(property.key) : undefined;
80
+ return key === undefined ? [] : [{ key, value: `${prefix}:${key}` }];
81
+ });
82
+ }
83
+ function definesPermissions(init) {
84
+ return (init.type === AST_NODE_TYPES.CallExpression &&
85
+ init.callee.type === AST_NODE_TYPES.Identifier &&
86
+ init.callee.name === 'definePermissions');
87
+ }
88
+ function keyOf(key) {
89
+ return key.type === AST_NODE_TYPES.Identifier ? key.name : stringOf(key);
90
+ }
91
+ function stringOf(node) {
92
+ if (node.type === AST_NODE_TYPES.Literal) {
93
+ return typeof node.value === 'string' ? node.value : undefined;
94
+ }
95
+ const [only] = node.type === AST_NODE_TYPES.TemplateLiteral && node.expressions.length === 0 ? node.quasis : [];
96
+ return only?.value.cooked ?? undefined;
97
+ }
98
+ function writtenAs(name, key) {
99
+ return IDENTIFIER.test(key) ? `${name}.${key}` : `${name}['${key}']`;
100
+ }
101
+ /** A context speaks its own language; the shared kernel is read by every layer; the platform by itself and by the edges of the contexts. */
102
+ function readerOf(location) {
103
+ if (location.area === 'context') {
104
+ return { context: location.context };
105
+ }
106
+ return location.area === 'shared-kernel' ? 'everywhere' : 'platform';
107
+ }
108
+ //# sourceMappingURL=values-declared-in.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values-declared-in.js","sourceRoot":"","sources":["../../../src/support/vocabularies/values-declared-in.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.5.0";
1
+ export declare const VERSION = "0.7.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.5.0';
1
+ export const VERSION = '0.7.0';
2
2
  //# sourceMappingURL=version.js.map
@@ -0,0 +1,59 @@
1
+ # ddd-ts-kit/clean-no-magic-number
2
+
3
+ Architecture id: `clean/no-magic-number`. Default severity: `error`.
4
+
5
+ Applies to: `domain/` and `application/` of every context of a project whose config says `"stack.literals": "named"`, which `init` writes (a config that does not say, as before 0.6, keeps the rule silent); tests excluded.
6
+
7
+ ## Why
8
+
9
+ `hours * 60`, `limit = 100`, `padStart(2, '0')`: a number in the middle of the model says neither what it is nor who decided it. The second copy of it drifts from the first, and a rule of the business (a booking window, a reminder delay, a page limit) hides in an expression. Named once, it reads as the language: `MINUTES_PER_HOUR`, `LONGEST_ADDRESS`, `BookingWindow.standard()`.
10
+
11
+ ## Reported
12
+
13
+ A number or bigint literal, the minus included, that is not:
14
+
15
+ - 0, 1 or -1 (configurable);
16
+ - an index, `items[2]`;
17
+ - a type, `type Hour = 7 | 8`, or the value of an enum member;
18
+ - in the initializer of a constant of the module (`const MINUTES_PER_HOUR = 60;`, an object or an array `as const` included) or of a `static readonly` field, with no function in between.
19
+
20
+ Incorrect:
21
+
22
+ ```ts
23
+ function minuteOf(hours: number, minutes: number): number {
24
+ return hours * 60 + minutes;
25
+ }
26
+ ```
27
+
28
+ Correct:
29
+
30
+ ```ts
31
+ const MINUTES_PER_HOUR = 60;
32
+
33
+ function minuteOf(hours: number, minutes: number): number {
34
+ return hours * MINUTES_PER_HOUR + minutes;
35
+ }
36
+ ```
37
+
38
+ ## Details
39
+
40
+ A duration, an amount, a limit or a rate of the business is better a value object than a constant (`BookingWindow`, `Money`): the constant names the number, the value object also carries its rules.
41
+
42
+ ## Options
43
+
44
+ `allow`: the numbers allowed anywhere, `[0, 1, -1]` by default.
45
+
46
+ ```js
47
+ 'ddd-ts-kit/clean-no-magic-number': ['error', { allow: [0, 1, -1, 2] }]
48
+ ```
49
+
50
+ `rules."clean/no-magic-number"` in `ddd-ts-kit.config.json` set to `off` silences the rule, and `// ddd-ts-kit-disable-next-line clean/no-magic-number -- <reason>` silences one line, exactly as for `ddd-ts-kit check`.
51
+
52
+ ## Limits
53
+
54
+ - A constant of a function body, `const limit = 100` inside `execute`, is reported: it is named, but decided where it is used.
55
+ - Infrastructure, presentation and the platform are not judged: a port number or a page size of a route are configuration.
56
+
57
+ ## With the CLI checker
58
+
59
+ None: the rule needs a syntax tree. `ddd-ts-kit check` knows its id so that the config can set its severity.
@@ -17,8 +17,8 @@ In a role file (the table below), other than `*.command.ts` and `*.query.ts`, wh
17
17
 
18
18
  On any class of `application/`, `infrastructure/`, `presentation/` or the context root:
19
19
 
20
- - `@IntegrationEventHandler(definition, { consumer })`, `@Policy(permission, { name })` or `@DomainEventHandler(Event, { name })` whose name is not a non-empty string literal: missing, empty, a variable, a template with a substitution, options held in a variable or only spread
21
- - `@DomainEventHandler(Event, { name })` whose `name` differs from the `name` literal of the event class, when that class is in view
20
+ - `@IntegrationEventHandler(definition, { consumer })`, `@Policy(permission, { name })` or `@DomainEventHandler(Event, { name })` whose name is not a non-empty string literal: missing, empty, a variable, a template with a substitution, options held in a variable or only spread. A domain event handler may instead read the name its event class declares, `@DomainEventHandler(InvoiceIssued, { name: InvoiceIssued.eventName })`, the class being the one it is given
21
+ - `@DomainEventHandler(Event, { name })` whose `name`, written out, differs from the name the event class declares, when that class is in view
22
22
 
23
23
  Under `domain/`:
24
24
 
@@ -92,7 +92,7 @@ A decorator counts when its name is one of the twelve declaration decorators and
92
92
 
93
93
  The role of a file is read from its suffix and its folder, as the generator writes them. A class is exported inline, by `export { A }` or by `export default A`. When a class carries another declaration decorator, only that is reported: fixing it also answers the missing one.
94
94
 
95
- The event class of `@DomainEventHandler` is in view when it is declared in the same file, or imported by name from a source of the project that exists on disk; that file is then parsed, syntax only, and its `readonly name = '...'` property is read (`as const` and `satisfies` are looked through). When the class cannot be found, or its name is not a literal, nothing is compared.
95
+ The event class of `@DomainEventHandler` is in view when it is declared in the same file, or imported by name from a source of the project that exists on disk; that file is then parsed, syntax only, and its `static readonly eventName = '...'` (or, as 0.5 wrote it, its `readonly name = '...'`) is read (`as const` and `satisfies` are looked through). When the class cannot be found, or its name is not a literal, nothing is compared.
96
96
 
97
97
  ## Options
98
98
 
@@ -10,14 +10,16 @@ An event name is a public address: consumers subscribe to it, the catalog lists
10
10
 
11
11
  ## Reported
12
12
 
13
- - in `domain/events/`: a `name` property or object key whose string is not `<this context>.<aggregate>.<fact>` in kebab-case
13
+ - in `domain/events/`: an `eventName` or `name` property or object key whose string is not `<this context>.<aggregate>.<fact>` in kebab-case
14
14
  - in `published-language/`: the `type` given to `defineIntegrationEvent`, and any other `type` holding a dotted string
15
15
 
16
16
  Incorrect:
17
17
 
18
18
  ```ts
19
19
  export class InvoiceIssued implements DomainEvent {
20
- readonly name = 'InvoiceIssued';
20
+ static readonly eventName = 'InvoiceIssued';
21
+
22
+ readonly name = InvoiceIssued.eventName;
21
23
  }
22
24
  ```
23
25
 
@@ -25,13 +27,15 @@ Correct:
25
27
 
26
28
  ```ts
27
29
  export class InvoiceIssued implements DomainEvent {
28
- readonly name = 'billing.invoice.issued';
30
+ static readonly eventName = 'billing.invoice.issued';
31
+
32
+ readonly name = InvoiceIssued.eventName;
29
33
  }
30
34
  ```
31
35
 
32
36
  ## Details
33
37
 
34
- Template literals without interpolation are read like strings.
38
+ Template literals without interpolation are read like strings. The name is declared once, in `eventName`, which the event carries in `name` and its reactions read (`{ name: InvoiceIssued.eventName }`); a `readonly name = '..'` written out, as before 0.6, is judged the same way.
35
39
 
36
40
  ## Options
37
41
 
@@ -0,0 +1,64 @@
1
+ # ddd-ts-kit/language-declared-vocabulary
2
+
3
+ Architecture id: `language/declared-vocabulary`. Default severity: `error`.
4
+
5
+ Applies to: every source under the source root of a project whose config says `"stack.literals": "named"`, which `init` writes (a config that does not say, as before 0.6, keeps the rule silent); tests, published languages, the relationship schema of the access model and the file that declares a value excluded.
6
+
7
+ ## Why
8
+
9
+ A status, a kind, a role or a permission is a word of the language whose values are a closed list. Spelled again as a string wherever it is compared, granted or stored, each copy can drift: a typo compiles, a renamed value leaves its old spelling behind, and nothing completes it in the editor. Declared once, it is read by its key, completed by the editor, and a parameter typed with it accepts nothing else. The value stays the same string on the wire and in the database.
10
+
11
+ ## Reported
12
+
13
+ A string literal, or a template literal without substitution, whose value is a value of a closed vocabulary the project declares:
14
+
15
+ - an object `as const` of string values exported next to the union type of the same name, `export type AppointmentStatus = (typeof AppointmentStatus)[keyof typeof AppointmentStatus]` (what `ddd-ts-kit generate vocabulary` writes, and the `Role` of the platform);
16
+ - a permission set, `export const billingPermissions = definePermissions('billing', { 'invoice.issue': .. })`, which declares the id `billing:invoice.issue`.
17
+
18
+ Incorrect:
19
+
20
+ ```ts
21
+ if (appointment.status === 'no-show') {
22
+ grants.push('billing:invoice.issue');
23
+ }
24
+ ```
25
+
26
+ Correct:
27
+
28
+ ```ts
29
+ if (appointment.status === AppointmentStatus.NoShow) {
30
+ grants.push(billingPermissions['invoice.issue']);
31
+ }
32
+ ```
33
+
34
+ ## Where a value is judged
35
+
36
+ A word means one thing in one context, and may mean something else next door; the rule follows the language of each place.
37
+
38
+ | Declared in | Judged in |
39
+ |---|---|
40
+ | a context (`domain/vocabularies/` of `billing`) | that context only: `issued` in `catalog` is another word |
41
+ | the platform (the `Role` of `<platformDir>/auth/role.ts`) | the platform, and the route groups `*.routes.ts` of the contexts, where a guard names a role |
42
+ | the shared kernel | everywhere |
43
+ | a permission set (`definePermissions`) | everywhere: a permission id names one permission of one context |
44
+
45
+ ## Details
46
+
47
+ A quoted key is a value spelled again and is reported: write it as a computed key, `[AppointmentStatus.NoShow]: 'No show'`, which also types the object by the vocabulary. An identifier key and the specifier of an import or an export are names and are not judged. A test spells the values a client sends on purpose, and a published language names the values of its contract itself: neither is judged. The message names the vocabulary, the file that declares it and what to write instead.
48
+
49
+ ## Options
50
+
51
+ None.
52
+
53
+ `rules."language/declared-vocabulary"` in `ddd-ts-kit.config.json` set to `off` silences the rule, and `// ddd-ts-kit-disable-next-line language/declared-vocabulary -- <reason>` silences one line, exactly as for `ddd-ts-kit check`.
54
+
55
+ ## Limits
56
+
57
+ - The vocabularies are read from the files of the source root on disk, again once a reading is five seconds old: an editor sees a new value after a few seconds, a lint run reads the project about once.
58
+ - The declaration is parsed: an exported `const` whose value is an object `as const` (or `as const satisfies ..`), each entry a key (a name or a quoted string) and a string literal, in either quote, comments allowed, next to `export type X = (typeof X)[keyof typeof X]` written that way. An object with a number, a spread, a method or a computed entry, or without that union type, declares nothing. `generate vocabulary` writes the form that is read.
59
+ - A value of the platform is matched by its value in every file of the platform: with the `Role` of an rbac project, `actor.type === 'system'` in the platform is reported although it compares a kind of actor, not a role. Declare that word in its own vocabulary (`ActorType.System`) and read it there, or silence the line with its reason.
60
+ - A value two vocabularies share is reported with both: the message names each and what to write for each.
61
+
62
+ ## With the CLI checker
63
+
64
+ `ddd-ts-kit check` holds the same rule on the text of the files of the project, with the same declarations and the same exemptions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ddd-ts-kit/eslint-plugin",
3
- "version": "0.5.0",
3
+ "version": "0.7.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": {