@pjts/eslint-style-rules 0.0.0-stage → 0.0.3

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 (113) hide show
  1. package/README.md +138 -2
  2. package/dist/index.d.ts +38 -0
  3. package/dist/index.js +232 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/lib/ast.d.ts +27 -0
  6. package/dist/lib/ast.js +60 -0
  7. package/dist/lib/ast.js.map +1 -0
  8. package/dist/lib/db.d.ts +13 -0
  9. package/dist/lib/db.js +50 -0
  10. package/dist/lib/db.js.map +1 -0
  11. package/dist/lib/messages.d.ts +13 -0
  12. package/dist/lib/messages.js +76 -0
  13. package/dist/lib/messages.js.map +1 -0
  14. package/dist/lib/rule.d.ts +9 -0
  15. package/dist/lib/rule.js +10 -0
  16. package/dist/lib/rule.js.map +1 -0
  17. package/dist/rules/app-class-suffix.d.ts +3 -0
  18. package/dist/rules/app-class-suffix.js +28 -0
  19. package/dist/rules/app-class-suffix.js.map +1 -0
  20. package/dist/rules/app-service-endpoints.d.ts +12 -0
  21. package/dist/rules/app-service-endpoints.js +79 -0
  22. package/dist/rules/app-service-endpoints.js.map +1 -0
  23. package/dist/rules/auth-access.d.ts +14 -0
  24. package/dist/rules/auth-access.js +122 -0
  25. package/dist/rules/auth-access.js.map +1 -0
  26. package/dist/rules/db-client-dependency.d.ts +11 -0
  27. package/dist/rules/db-client-dependency.js +74 -0
  28. package/dist/rules/db-client-dependency.js.map +1 -0
  29. package/dist/rules/db-writes-in-repositories.d.ts +12 -0
  30. package/dist/rules/db-writes-in-repositories.js +105 -0
  31. package/dist/rules/db-writes-in-repositories.js.map +1 -0
  32. package/dist/rules/decorated-class-contract.d.ts +6 -0
  33. package/dist/rules/decorated-class-contract.js +37 -0
  34. package/dist/rules/decorated-class-contract.js.map +1 -0
  35. package/dist/rules/entity-constructor-data.d.ts +6 -0
  36. package/dist/rules/entity-constructor-data.js +35 -0
  37. package/dist/rules/entity-constructor-data.js.map +1 -0
  38. package/dist/rules/event-sourced-aggregate.d.ts +15 -0
  39. package/dist/rules/event-sourced-aggregate.js +134 -0
  40. package/dist/rules/event-sourced-aggregate.js.map +1 -0
  41. package/dist/rules/find-one-naming.d.ts +7 -0
  42. package/dist/rules/find-one-naming.js +38 -0
  43. package/dist/rules/find-one-naming.js.map +1 -0
  44. package/dist/rules/import-only-in.d.ts +7 -0
  45. package/dist/rules/import-only-in.js +52 -0
  46. package/dist/rules/import-only-in.js.map +1 -0
  47. package/dist/rules/knex-first.d.ts +3 -0
  48. package/dist/rules/knex-first.js +28 -0
  49. package/dist/rules/knex-first.js.map +1 -0
  50. package/dist/rules/message-file.d.ts +18 -0
  51. package/dist/rules/message-file.js +118 -0
  52. package/dist/rules/message-file.js.map +1 -0
  53. package/dist/rules/message-handler.d.ts +19 -0
  54. package/dist/rules/message-handler.js +114 -0
  55. package/dist/rules/message-handler.js.map +1 -0
  56. package/dist/rules/message-name-reference.d.ts +7 -0
  57. package/dist/rules/message-name-reference.js +52 -0
  58. package/dist/rules/message-name-reference.js.map +1 -0
  59. package/dist/rules/message-names.d.ts +7 -0
  60. package/dist/rules/message-names.js +80 -0
  61. package/dist/rules/message-names.js.map +1 -0
  62. package/dist/rules/module-layout.d.ts +9 -0
  63. package/dist/rules/module-layout.js +71 -0
  64. package/dist/rules/module-layout.js.map +1 -0
  65. package/dist/rules/module-service-getters.d.ts +19 -0
  66. package/dist/rules/module-service-getters.js +132 -0
  67. package/dist/rules/module-service-getters.js.map +1 -0
  68. package/dist/rules/no-async-in-domain.d.ts +2 -0
  69. package/dist/rules/no-async-in-domain.js +116 -0
  70. package/dist/rules/no-async-in-domain.js.map +1 -0
  71. package/dist/rules/no-duplicate-sdk-types.d.ts +6 -0
  72. package/dist/rules/no-duplicate-sdk-types.js +40 -0
  73. package/dist/rules/no-duplicate-sdk-types.js.map +1 -0
  74. package/dist/rules/no-entity-assembly-in-app.d.ts +7 -0
  75. package/dist/rules/no-entity-assembly-in-app.js +37 -0
  76. package/dist/rules/no-entity-assembly-in-app.js.map +1 -0
  77. package/dist/rules/no-entity-mutation-outside-domain.d.ts +11 -0
  78. package/dist/rules/no-entity-mutation-outside-domain.js +68 -0
  79. package/dist/rules/no-entity-mutation-outside-domain.js.map +1 -0
  80. package/dist/rules/no-message-construction-outside-domain.d.ts +15 -0
  81. package/dist/rules/no-message-construction-outside-domain.js +45 -0
  82. package/dist/rules/no-message-construction-outside-domain.js.map +1 -0
  83. package/dist/rules/no-reconstitute.d.ts +3 -0
  84. package/dist/rules/no-reconstitute.js +22 -0
  85. package/dist/rules/no-reconstitute.js.map +1 -0
  86. package/dist/rules/port-file.d.ts +9 -0
  87. package/dist/rules/port-file.js +94 -0
  88. package/dist/rules/port-file.js.map +1 -0
  89. package/dist/rules/port-has-adapters.d.ts +9 -0
  90. package/dist/rules/port-has-adapters.js +62 -0
  91. package/dist/rules/port-has-adapters.js.map +1 -0
  92. package/dist/rules/repository-naming.d.ts +19 -0
  93. package/dist/rules/repository-naming.js +122 -0
  94. package/dist/rules/repository-naming.js.map +1 -0
  95. package/dist/rules/repository-serialization.d.ts +6 -0
  96. package/dist/rules/repository-serialization.js +50 -0
  97. package/dist/rules/repository-serialization.js.map +1 -0
  98. package/dist/rules/return-entities.d.ts +6 -0
  99. package/dist/rules/return-entities.js +38 -0
  100. package/dist/rules/return-entities.js.map +1 -0
  101. package/dist/rules/save-contract.d.ts +7 -0
  102. package/dist/rules/save-contract.js +41 -0
  103. package/dist/rules/save-contract.js.map +1 -0
  104. package/dist/rules/test-location.d.ts +14 -0
  105. package/dist/rules/test-location.js +94 -0
  106. package/dist/rules/test-location.js.map +1 -0
  107. package/dist/rules/throw-app-error.d.ts +12 -0
  108. package/dist/rules/throw-app-error.js +68 -0
  109. package/dist/rules/throw-app-error.js.map +1 -0
  110. package/dist/rules/trackable-repository.d.ts +10 -0
  111. package/dist/rules/trackable-repository.js +97 -0
  112. package/dist/rules/trackable-repository.js.map +1 -0
  113. package/package.json +46 -4
@@ -0,0 +1,97 @@
1
+ "use strict";
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"));
6
+ const rule_1 = require("../lib/rule");
7
+ const ast_1 = require("../lib/ast");
8
+ /** Resolved file → does it declare `class <name> … extends <base>` (per lint run). */
9
+ const eventSourcedCache = new Map();
10
+ const resolveSource = (fromFile, source) => {
11
+ if (!source.startsWith('.'))
12
+ return null;
13
+ const base = path_1.default.resolve(path_1.default.dirname(fromFile), source);
14
+ for (const candidate of [`${base}.ts`, path_1.default.join(base, 'index.ts')])
15
+ if (fs_1.default.existsSync(candidate))
16
+ return candidate;
17
+ return null;
18
+ };
19
+ /** Follows one level of `export … from './X'` re-exports (module barrels). */
20
+ const declaresEventSourced = (file, name, base, depth = 0) => {
21
+ const key = `${file}#${name}`;
22
+ if (eventSourcedCache.has(key))
23
+ return eventSourcedCache.get(key);
24
+ const source = fs_1.default.readFileSync(file, 'utf8');
25
+ let result = new RegExp(`class\\s+${name}\\b[^{]*\\bextends\\s+${base}\\b`).test(source);
26
+ if (!result && depth < 2) {
27
+ for (const match of source.matchAll(/export\s+(?:\{[^}]*\}|\*)\s+from\s+'([^']+)'/g)) {
28
+ const target = resolveSource(file, match[1]);
29
+ if (target && declaresEventSourced(target, name, base, depth + 1)) {
30
+ result = true;
31
+ break;
32
+ }
33
+ }
34
+ }
35
+ eventSourcedCache.set(key, result);
36
+ return result;
37
+ };
38
+ /**
39
+ * Repositories built on the pjx persistence bases (`RepositoryBase`, `OutboxRepository`):
40
+ *
41
+ * - every `deserialize…` method carries `@reconstitute` — it marks the entity as restored and copies
42
+ * its version, so `save()` updates (with the optimistic-lock check) instead of inserting a duplicate;
43
+ * - an event-sourced aggregate (`extends EventSourceable`) is persisted by an `…OutboxRepository`, so
44
+ * its emitted events reach the outbox in the same transaction as its state.
45
+ */
46
+ exports.default = (0, rule_1.defineRule)({
47
+ meta: {
48
+ type: 'problem',
49
+ docs: { description: 'Persist trackable and event-sourced aggregates correctly' },
50
+ messages: {
51
+ reconstitute: '`{{method}}` rebuilds a persisted entity — decorate it with @{{decorator}} so save() updates instead of inserting.',
52
+ outbox: '"{{entity}}" is event-sourced — "{{name}}" must extend an …OutboxRepository so its events reach the outbox with its state.',
53
+ },
54
+ schema: [{
55
+ type: 'object',
56
+ properties: {
57
+ bases: { type: 'array', items: { type: 'string' } },
58
+ decorator: { type: 'string' },
59
+ outboxPattern: { type: 'string' },
60
+ eventSourcedBase: { type: 'string' },
61
+ },
62
+ additionalProperties: false,
63
+ }],
64
+ },
65
+ create(context) {
66
+ const { bases = ['RepositoryBase', 'OutboxRepository'], decorator = 'reconstitute', outboxPattern = 'OutboxRepository$', eventSourcedBase = 'EventSourceable', } = context.options[0] ?? {};
67
+ const imports = new Map();
68
+ const isPersistenceBase = (name) => !!name && (bases.includes(name) || new RegExp(outboxPattern).test(name));
69
+ return {
70
+ ImportDeclaration(node) {
71
+ for (const specifier of node.specifiers)
72
+ imports.set(specifier.local.name, node.source.value);
73
+ },
74
+ ClassDeclaration(node) {
75
+ const superName = node.superClass?.name;
76
+ if (!isPersistenceBase(superName))
77
+ return;
78
+ for (const member of node.body.body) {
79
+ if (member.type !== 'MethodDefinition' || !/^deserialize/.test((0, ast_1.memberName)(member) ?? ''))
80
+ continue;
81
+ if (!(0, ast_1.decoratorNames)(member).includes(decorator)) {
82
+ context.report({ node: member.key, messageId: 'reconstitute', data: { method: (0, ast_1.memberName)(member), decorator } });
83
+ }
84
+ }
85
+ if (new RegExp(outboxPattern).test(superName))
86
+ return;
87
+ const entityType = (node.superTypeArguments ?? node.superTypeParameters)?.params?.[0];
88
+ const entity = entityType?.type === 'TSTypeReference' && entityType.typeName.type === 'Identifier' ? entityType.typeName.name : null;
89
+ const file = entity && imports.has(entity) ? resolveSource(context.filename, imports.get(entity)) : null;
90
+ if (entity && file && declaresEventSourced(file, entity, eventSourcedBase)) {
91
+ context.report({ node: node.superClass, messageId: 'outbox', data: { entity, name: node.id?.name ?? '(anonymous)' } });
92
+ }
93
+ },
94
+ };
95
+ },
96
+ });
97
+ //# sourceMappingURL=trackable-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trackable-repository.js","sourceRoot":"","sources":["../../src/rules/trackable-repository.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,48 @@
1
1
  {
2
2
  "name": "@pjts/eslint-style-rules",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.0.3",
4
+ "description": "Piotr Józefów DDD utility package — ESLint rules and flat-config preset enforcing the pjts DDD layout and conventions",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "author": "Piotr Józefów",
8
+ "license": "MIT",
9
+ "keywords": [
10
+ "eslint",
11
+ "eslintplugin",
12
+ "eslint-plugin",
13
+ "ddd",
14
+ "pjts"
15
+ ],
16
+ "scripts": {
17
+ "lint": "eslint src/",
18
+ "test": "NODE_ENV=test jest --coverage=false --verbose",
19
+ "test:watch": "NODE_ENV=test jest --coverage=false --watchAll --testNamePattern=",
20
+ "build": "rm -rf ./dist && tsc",
21
+ "package": "npm run build && npm publish --access=public",
22
+ "prepare": "npm version patch"
23
+ },
24
+ "peerDependencies": {
25
+ "eslint": ">=9.24.0",
26
+ "typescript-eslint": ">=8.0.0"
27
+ },
28
+ "peerDependenciesMeta": {
29
+ "typescript-eslint": {
30
+ "optional": true
31
+ }
32
+ },
33
+ "devDependencies": {
34
+ "@types/jest": "29.5.14",
35
+ "@types/node": "18.13.0",
36
+ "eslint": "9.32.0",
37
+ "jest": "29.7.0",
38
+ "ts-jest": "29.2.5",
39
+ "typescript": "5.8.3",
40
+ "typescript-eslint": "8.38.0"
41
+ },
42
+ "publishConfig": {
43
+ "registry": "https://registry.npmjs.org"
44
+ },
45
+ "dependencies": {
46
+ "tslib": "2.8.1"
47
+ }
48
+ }