@jamesaphoenix/tx-core 0.5.4 → 0.5.6

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 (42) hide show
  1. package/README.md +4 -4
  2. package/dist/errors.d.ts +2 -0
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/errors.js.map +1 -1
  5. package/dist/index.d.ts +2 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/repo/attempt-repo.d.ts.map +1 -1
  10. package/dist/repo/attempt-repo.js +19 -6
  11. package/dist/repo/attempt-repo.js.map +1 -1
  12. package/dist/repo/dep-repo.d.ts.map +1 -1
  13. package/dist/repo/dep-repo.js +37 -20
  14. package/dist/repo/dep-repo.js.map +1 -1
  15. package/dist/repo/learning-repo.d.ts.map +1 -1
  16. package/dist/repo/learning-repo.js +15 -2
  17. package/dist/repo/learning-repo.js.map +1 -1
  18. package/dist/repo/task-repo.d.ts +8 -0
  19. package/dist/repo/task-repo.d.ts.map +1 -1
  20. package/dist/repo/task-repo.js +137 -9
  21. package/dist/repo/task-repo.js.map +1 -1
  22. package/dist/services/doc-service.d.ts.map +1 -1
  23. package/dist/services/doc-service.js +28 -6
  24. package/dist/services/doc-service.js.map +1 -1
  25. package/dist/services/ready-service.d.ts.map +1 -1
  26. package/dist/services/ready-service.js +76 -41
  27. package/dist/services/ready-service.js.map +1 -1
  28. package/dist/services/task-service.d.ts +2 -0
  29. package/dist/services/task-service.d.ts.map +1 -1
  30. package/dist/services/task-service.js +43 -2
  31. package/dist/services/task-service.js.map +1 -1
  32. package/dist/services/tracing-service.js +1 -1
  33. package/dist/services/tracing-service.js.map +1 -1
  34. package/dist/utils/doc-renderer.d.ts +3 -1
  35. package/dist/utils/doc-renderer.d.ts.map +1 -1
  36. package/dist/utils/doc-renderer.js +95 -0
  37. package/dist/utils/doc-renderer.js.map +1 -1
  38. package/dist/utils/ears-validator.d.ts +10 -0
  39. package/dist/utils/ears-validator.d.ts.map +1 -0
  40. package/dist/utils/ears-validator.js +170 -0
  41. package/dist/utils/ears-validator.js.map +1 -0
  42. package/package.json +1 -1
@@ -0,0 +1,170 @@
1
+ import { EARS_PATTERNS } from "@jamesaphoenix/tx-types";
2
+ const EARS_ID_PATTERN = /^EARS-[A-Z0-9]+-\d{3}$/;
3
+ const EARS_PRIORITIES = ["must", "should", "could", "wont"];
4
+ const validPatternSet = new Set(EARS_PATTERNS);
5
+ const validPrioritySet = new Set(EARS_PRIORITIES);
6
+ const asRecord = (value) => {
7
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
8
+ return null;
9
+ }
10
+ return value;
11
+ };
12
+ const pickString = (obj, key) => {
13
+ const value = obj[key];
14
+ return typeof value === "string" ? value.trim() : null;
15
+ };
16
+ const requiredPatternField = (pattern) => {
17
+ switch (pattern) {
18
+ case "event_driven":
19
+ return "trigger";
20
+ case "state_driven":
21
+ return "state";
22
+ case "unwanted":
23
+ return "condition";
24
+ case "optional":
25
+ return "feature";
26
+ default:
27
+ return null;
28
+ }
29
+ };
30
+ export const validateEarsRequirements = (requirements) => {
31
+ const errors = [];
32
+ const seenIds = new Set();
33
+ requirements.forEach((entry, index) => {
34
+ const req = asRecord(entry);
35
+ if (!req) {
36
+ errors.push({
37
+ index,
38
+ id: null,
39
+ field: "ears_requirements",
40
+ code: "invalid_type",
41
+ message: "Each EARS requirement must be an object.",
42
+ });
43
+ return;
44
+ }
45
+ const id = pickString(req, "id");
46
+ const pattern = pickString(req, "pattern");
47
+ const system = pickString(req, "system");
48
+ const response = pickString(req, "response");
49
+ const priority = pickString(req, "priority");
50
+ if (!id) {
51
+ errors.push({
52
+ index,
53
+ id: null,
54
+ field: "id",
55
+ code: "missing_required",
56
+ message: "Field 'id' is required.",
57
+ });
58
+ }
59
+ else {
60
+ if (!EARS_ID_PATTERN.test(id)) {
61
+ errors.push({
62
+ index,
63
+ id,
64
+ field: "id",
65
+ code: "invalid_format",
66
+ message: "Field 'id' must match EARS-<SYSTEM>-NNN (e.g. EARS-FL-001).",
67
+ });
68
+ }
69
+ if (seenIds.has(id)) {
70
+ errors.push({
71
+ index,
72
+ id,
73
+ field: "id",
74
+ code: "duplicate_id",
75
+ message: `Duplicate EARS requirement id '${id}'.`,
76
+ });
77
+ }
78
+ else {
79
+ seenIds.add(id);
80
+ }
81
+ }
82
+ if (!pattern) {
83
+ errors.push({
84
+ index,
85
+ id,
86
+ field: "pattern",
87
+ code: "missing_required",
88
+ message: "Field 'pattern' is required.",
89
+ });
90
+ }
91
+ else if (!validPatternSet.has(pattern)) {
92
+ errors.push({
93
+ index,
94
+ id,
95
+ field: "pattern",
96
+ code: "invalid_value",
97
+ message: `Invalid EARS pattern '${pattern}'. Valid patterns: ${EARS_PATTERNS.join(", ")}.`,
98
+ });
99
+ }
100
+ if (!system) {
101
+ errors.push({
102
+ index,
103
+ id,
104
+ field: "system",
105
+ code: "missing_required",
106
+ message: "Field 'system' is required.",
107
+ });
108
+ }
109
+ if (!response) {
110
+ errors.push({
111
+ index,
112
+ id,
113
+ field: "response",
114
+ code: "missing_required",
115
+ message: "Field 'response' is required.",
116
+ });
117
+ }
118
+ if (priority && !validPrioritySet.has(priority)) {
119
+ errors.push({
120
+ index,
121
+ id,
122
+ field: "priority",
123
+ code: "invalid_value",
124
+ message: `Invalid priority '${priority}'. Valid priorities: ${EARS_PRIORITIES.join(", ")}.`,
125
+ });
126
+ }
127
+ if (pattern && validPatternSet.has(pattern)) {
128
+ const requiredField = requiredPatternField(pattern);
129
+ if (requiredField) {
130
+ const requiredValue = pickString(req, requiredField);
131
+ if (!requiredValue) {
132
+ errors.push({
133
+ index,
134
+ id,
135
+ field: requiredField,
136
+ code: "missing_required",
137
+ message: `Pattern '${pattern}' requires field '${requiredField}'.`,
138
+ });
139
+ }
140
+ }
141
+ if (pattern === "complex") {
142
+ const hasClause = Boolean(pickString(req, "trigger")) ||
143
+ Boolean(pickString(req, "state")) ||
144
+ Boolean(pickString(req, "condition")) ||
145
+ Boolean(pickString(req, "feature"));
146
+ if (!hasClause) {
147
+ errors.push({
148
+ index,
149
+ id,
150
+ field: "pattern",
151
+ code: "missing_required",
152
+ message: "Pattern 'complex' requires at least one clause: trigger, state, condition, or feature.",
153
+ });
154
+ }
155
+ }
156
+ }
157
+ });
158
+ return errors;
159
+ };
160
+ export const formatEarsValidationErrors = (errors) => {
161
+ return errors
162
+ .map((error) => {
163
+ const location = error.id
164
+ ? `${error.id}`
165
+ : `entry #${error.index + 1}`;
166
+ return `${location} (${error.field}): ${error.message}`;
167
+ })
168
+ .join("; ");
169
+ };
170
+ //# sourceMappingURL=ears-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ears-validator.js","sourceRoot":"","sources":["../../src/utils/ears-validator.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jamesaphoenix/tx-core",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "Core business logic for tx - Effect-TS services and repositories",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",