xdbc 1.0.207 → 1.0.209

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 (75) hide show
  1. package/Assessment.html +350 -0
  2. package/Assessment.md +507 -51
  3. package/CHANGELOG.md +55 -0
  4. package/CONTRIBUTING.md +129 -17
  5. package/README.md +373 -71
  6. package/SECURITY.md +60 -18
  7. package/SUPPORT.md +65 -0
  8. package/__tests__/DBC/DEFINED.test.ts +53 -0
  9. package/__tests__/DBC/Decorators.test.ts +365 -0
  10. package/__tests__/DBC/GREATER.test.ts +8 -6
  11. package/__tests__/DBC/HasAttribute.test.ts +56 -0
  12. package/__tests__/DBC/IF.test.ts +52 -0
  13. package/__tests__/DBC/JSON.Parse.test.ts +1 -1
  14. package/__tests__/DBC/OR.test.ts +1 -1
  15. package/__tests__/DBC/REGEX.test.ts +1 -1
  16. package/__tests__/DBC/TYPE.test.ts +1 -1
  17. package/__tests__/DBC/UNDEFINED.test.ts +45 -0
  18. package/__tests__/DBC/ZOD.test.ts +54 -0
  19. package/jest.config.js +21 -0
  20. package/package.json +4 -5
  21. package/src/DBC/AE.ts +10 -6
  22. package/src/DBC/COMPARISON/GREATER.ts +11 -7
  23. package/src/DBC/COMPARISON/GREATER_OR_EQUAL.ts +14 -10
  24. package/src/DBC/COMPARISON/LESS.ts +14 -10
  25. package/src/DBC/COMPARISON/LESS_OR_EQUAL.ts +14 -10
  26. package/src/DBC/COMPARISON.ts +20 -43
  27. package/src/DBC/DEFINED.ts +4 -23
  28. package/src/DBC/EQ/DIFFERENT.ts +21 -56
  29. package/src/DBC/EQ.ts +7 -26
  30. package/src/DBC/HasAttribute.ts +9 -26
  31. package/src/DBC/IF.ts +8 -27
  32. package/src/DBC/INSTANCE.ts +5 -22
  33. package/src/DBC/JSON.OP.ts +4 -34
  34. package/src/DBC/JSON.Parse.ts +5 -25
  35. package/src/DBC/OR.ts +5 -14
  36. package/src/DBC/REGEX.ts +41 -40
  37. package/src/DBC/TYPE.ts +6 -25
  38. package/src/DBC/UNDEFINED.ts +3 -22
  39. package/src/DBC/ZOD.ts +10 -27
  40. package/src/DBC.ts +223 -55
  41. package/tsconfig.json +7 -4
  42. package/tsconfig.test.json +12 -0
  43. package/.parcel-cache/bf96c58b6061a62a-BundleGraph +0 -0
  44. package/.parcel-cache/d7c812d65aeeac59-AssetGraph +0 -0
  45. package/.parcel-cache/data.mdb +0 -0
  46. package/.parcel-cache/e81759c1f106a17f-RequestGraph +0 -0
  47. package/.parcel-cache/fe0db3c4eb428be2-AssetGraph +0 -0
  48. package/.parcel-cache/lock.mdb +0 -0
  49. package/.parcel-cache/snapshot-e81759c1f106a17f.txt +0 -4609
  50. package/dist/DBC/AE.js +0 -173
  51. package/dist/DBC/COMPARISON/GREATER.js +0 -21
  52. package/dist/DBC/COMPARISON/GREATER_OR_EQUAL.js +0 -21
  53. package/dist/DBC/COMPARISON/LESS.js +0 -21
  54. package/dist/DBC/COMPARISON/LESS_OR_EQUAL.js +0 -21
  55. package/dist/DBC/COMPARISON.js +0 -99
  56. package/dist/DBC/DEFINED.js +0 -99
  57. package/dist/DBC/EQ/DIFFERENT.js +0 -21
  58. package/dist/DBC/EQ.js +0 -100
  59. package/dist/DBC/GREATER.js +0 -99
  60. package/dist/DBC/HasAttribute.js +0 -108
  61. package/dist/DBC/IF.js +0 -99
  62. package/dist/DBC/INSTANCE.js +0 -93
  63. package/dist/DBC/JSON.OP.js +0 -133
  64. package/dist/DBC/JSON.Parse.js +0 -114
  65. package/dist/DBC/OR.js +0 -113
  66. package/dist/DBC/REGEX.js +0 -110
  67. package/dist/DBC/TYPE.js +0 -87
  68. package/dist/DBC/ZOD.js +0 -114
  69. package/dist/DBC.js +0 -336
  70. package/dist/Demo.js +0 -290
  71. package/dist/Test.html +0 -18
  72. package/dist/bundle.js +0 -2064
  73. package/dist/index.html +0 -18
  74. package/jest.config.ts +0 -20
  75. package/xpackage-lock.json +0 -122
package/SECURITY.md CHANGED
@@ -1,36 +1,78 @@
1
1
  # Security Policy
2
2
 
3
- ## Introduction
3
+ ## Supported Versions
4
4
 
5
- This security policy outlines our commitment to ensuring the security of XDBC and its users.
5
+ | Version | Supported |
6
+ |---|---|
7
+ | 1.0.x (latest) | Yes |
8
+ | < 1.0.0 | No |
6
9
 
7
- ## Reporting Vulnerabilities
10
+ Only the latest published version on npm receives security patches. Users are encouraged to stay up to date.
8
11
 
9
- To report a security vulnerability, please send an email to [Security@WaXCode.net](mailto:Security@WaXCode.net). Please include the following information:
12
+ ---
10
13
 
11
- * Description of the vulnerability
12
- * Steps to reproduce
13
- * Affected components/versions
14
- * Potential impact
14
+ ## Reporting a Vulnerability
15
15
 
16
- We will acknowledge your report within 24 - 48 hours and provide updates as we investigate.
16
+ **Do not open a public GitHub issue for security vulnerabilities.**
17
17
 
18
- ## Vulnerability Handling
18
+ To report a security concern, please email **[Security@WaXCode.net](mailto:Security@WaXCode.net)** with the following details:
19
19
 
20
- We will triage and assess reported vulnerabilities, prioritizing them based on severity. We will develop and test patches, and communicate updates to users.
20
+ - Description of the vulnerability
21
+ - Steps to reproduce or a proof of concept
22
+ - Affected component(s) and version(s)
23
+ - Potential impact and severity assessment
24
+ - Suggested fix, if any
21
25
 
22
- ## Disclosure Policy
26
+ ### Response Timeline
23
27
 
24
- We will publicly disclose vulnerabilities after a fix is available. We may provide credit to reporters with their consent.
28
+ | Stage | Timeframe |
29
+ |---|---|
30
+ | Acknowledgment of report | Within 48 hours |
31
+ | Initial triage and severity assessment | Within 5 business days |
32
+ | Patch development and internal testing | Dependent on severity |
33
+ | Public disclosure (after fix is available) | Coordinated with reporter |
25
34
 
26
- ## Security Best Practices
35
+ ---
27
36
 
28
- We follow secure coding standards and regularly update dependencies.
37
+ ## Vulnerability Handling Process
38
+
39
+ 1. **Triage** — The report is reviewed, reproduced, and assigned a severity level (Critical / High / Medium / Low).
40
+ 2. **Fix** — A patch is developed and tested against the current release.
41
+ 3. **Release** — A patched version is published to npm.
42
+ 4. **Disclosure** — A security advisory is published on GitHub after the fix is available. The reporter will be credited (with consent).
43
+
44
+ ---
45
+
46
+ ## Scope
47
+
48
+ This policy covers the XDBC npm package (`xdbc`) and its source code. It does **not** cover:
49
+
50
+ - Third-party dependencies (report those to the respective maintainers)
51
+ - The generated documentation site
52
+ - User applications that consume XDBC
53
+
54
+ ---
55
+
56
+ ## Security Best Practices for Users
57
+
58
+ - Keep XDBC updated to the latest version
59
+ - Run `npm audit` regularly to check for transitive dependency vulnerabilities
60
+ - Do not disable contract checking in security-sensitive paths without understanding the implications
61
+ - Avoid passing untrusted input directly to `path` resolution without validation
62
+
63
+ ---
29
64
 
30
65
  ## Responsible Disclosure
31
66
 
32
- We encourage responsible disclosure and will not take legal action against reporters.
67
+ We are committed to responsible disclosure and will not pursue legal action against individuals who:
68
+
69
+ - Report vulnerabilities in good faith
70
+ - Allow reasonable time for a fix before public disclosure
71
+ - Do not exploit the vulnerability beyond what is necessary to demonstrate it
72
+
73
+ ---
33
74
 
34
- ## Policy Updates
75
+ ## Contact
35
76
 
36
- This policy will be reviewed and updated regularly.
77
+ Security reports: **[Security@WaXCode.net](mailto:Security@WaXCode.net)**
78
+ General inquiries: **[XDBC@WaXCode.net](mailto:XDBC@WaXCode.net)**
package/SUPPORT.md ADDED
@@ -0,0 +1,65 @@
1
+ # Support
2
+
3
+ ## Getting Help
4
+
5
+ If you need help using XDBC, there are several resources available:
6
+
7
+ ### Documentation
8
+
9
+ - **[API Reference](https://callaris.github.io/XDBC/)** — Full generated API documentation
10
+ - **[README](README.md)** — Quick start guide, contracts reference, and configuration
11
+ - **[Demo.ts](src/Demo.ts)** — Annotated usage examples
12
+
13
+ ### Community
14
+
15
+ - **[GitHub Discussions](https://github.com/CallariS/XDBC/discussions)** — Ask questions, share ideas, and connect with other users
16
+ - **[GitHub Issues](https://github.com/CallariS/XDBC/issues)** — Report bugs or request features
17
+
18
+ ### Direct Contact
19
+
20
+ - **Email**: [XDBC@WaXCode.net](mailto:XDBC@WaXCode.net)
21
+
22
+ ---
23
+
24
+ ## Frequently Asked Questions
25
+
26
+ ### How do I install XDBC?
27
+
28
+ ```sh
29
+ npm install xdbc
30
+ ```
31
+
32
+ Ensure your `tsconfig.json` has `experimentalDecorators` and `emitDecoratorMetadata` enabled.
33
+
34
+ ### Why do I need `@DBC.ParamvalueProvider`?
35
+
36
+ TypeScript parameter decorators cannot access the actual parameter values at runtime. The `@DBC.ParamvalueProvider` method decorator intercepts the method call and captures parameter values so that `PRE` contracts can validate them.
37
+
38
+ ### Can I disable contract checking in production?
39
+
40
+ Yes. Access the DBC instance and toggle execution settings:
41
+
42
+ ```typescript
43
+ const dbc = (globalThis as any).WaXCode.DBC;
44
+ dbc.executionSettings.checkPreconditions = false;
45
+ dbc.executionSettings.checkPostconditions = false;
46
+ dbc.executionSettings.checkInvariants = false;
47
+ ```
48
+
49
+ ### Does XDBC work in Node.js?
50
+
51
+ Yes. XDBC uses `globalThis` for host resolution and works in both browser and Node.js environments.
52
+
53
+ ### How do I report a security vulnerability?
54
+
55
+ Do not open a public issue. Email **[Security@WaXCode.net](mailto:Security@WaXCode.net)** directly. See [SECURITY.md](SECURITY.md) for the full policy.
56
+
57
+ ---
58
+
59
+ ## Sponsoring
60
+
61
+ If XDBC is useful in your work, consider supporting its development:
62
+
63
+ - **[GitHub Sponsors](https://github.com/sponsors/CallariS)**
64
+ - **[Patreon](https://patreon.com/salvatorecallari)**
65
+ - **[PayPal](https://paypal.me/CallariS)**
@@ -0,0 +1,53 @@
1
+ import { DEFINED } from "../../src/DBC/DEFINED";
2
+
3
+ describe("DEFINED", () => {
4
+ const defined = new DEFINED();
5
+
6
+ test("Should not report infringement with a string value", () => {
7
+ expect(defined.check("hello")).toBe(true);
8
+ });
9
+
10
+ test("Should not report infringement with a number value", () => {
11
+ expect(defined.check(42)).toBe(true);
12
+ });
13
+
14
+ test("Should not report infringement with an empty string", () => {
15
+ expect(defined.check("")).toBe(true);
16
+ });
17
+
18
+ test("Should not report infringement with zero", () => {
19
+ expect(defined.check(0)).toBe(true);
20
+ });
21
+
22
+ test("Should not report infringement with false", () => {
23
+ expect(defined.check(false)).toBe(true);
24
+ });
25
+
26
+ test("Should report infringement with null", () => {
27
+ expect(typeof defined.check(null)).toBe("string");
28
+ });
29
+
30
+ test("Should report infringement with undefined", () => {
31
+ expect(typeof defined.check(undefined)).toBe("string");
32
+ });
33
+
34
+ describe("checkAlgorithm", () => {
35
+ test("Should return true for defined values", () => {
36
+ expect(DEFINED.checkAlgorithm("test")).toBe(true);
37
+ expect(DEFINED.checkAlgorithm(0)).toBe(true);
38
+ expect(DEFINED.checkAlgorithm(false)).toBe(true);
39
+ });
40
+
41
+ test("Should return string for null", () => {
42
+ const result = DEFINED.checkAlgorithm(null);
43
+ expect(typeof result).toBe("string");
44
+ expect(result).toContain("NULL");
45
+ });
46
+
47
+ test("Should return string for undefined", () => {
48
+ const result = DEFINED.checkAlgorithm(undefined);
49
+ expect(typeof result).toBe("string");
50
+ expect(result).toContain("UNDEFINED");
51
+ });
52
+ });
53
+ });
@@ -0,0 +1,365 @@
1
+ import "reflect-metadata";
2
+ import { DBC } from "../../src/DBC";
3
+ import { REGEX } from "../../src/DBC/REGEX";
4
+ import { TYPE } from "../../src/DBC/TYPE";
5
+ import { EQ } from "../../src/DBC/EQ";
6
+ import { GREATER } from "../../src/DBC/COMPARISON/GREATER";
7
+ import { GREATER_OR_EQUAL } from "../../src/DBC/COMPARISON/GREATER_OR_EQUAL";
8
+ import { LESS } from "../../src/DBC/COMPARISON/LESS";
9
+ import { LESS_OR_EQUAL } from "../../src/DBC/COMPARISON/LESS_OR_EQUAL";
10
+ import { DIFFERENT } from "../../src/DBC/EQ/DIFFERENT";
11
+ import { INSTANCE } from "../../src/DBC/INSTANCE";
12
+ import { AE } from "../../src/DBC/AE";
13
+ import { OR } from "../../src/DBC/OR";
14
+
15
+ // Ensure a DBC instance is registered (DBC.ts module-level code does this via DBC.register)
16
+ const dbc: DBC = (window as any).WaXCode?.DBC;
17
+
18
+ describe("Decorator: @PRE (Preconditions)", () => {
19
+ class PreTestSubject {
20
+ @DBC.ParamvalueProvider
21
+ public regexPre(@REGEX.PRE(/^[A-Z]+$/) input: string): string {
22
+ return input;
23
+ }
24
+
25
+ @DBC.ParamvalueProvider
26
+ public typePre(@TYPE.PRE("string") input: unknown): unknown {
27
+ return input;
28
+ }
29
+
30
+ @DBC.ParamvalueProvider
31
+ public eqPre(@EQ.PRE("hello") input: string): string {
32
+ return input;
33
+ }
34
+
35
+ @DBC.ParamvalueProvider
36
+ public greaterPre(@GREATER.PRE(5) input: number): number {
37
+ return input;
38
+ }
39
+
40
+ @DBC.ParamvalueProvider
41
+ public greaterOrEqualPre(@GREATER_OR_EQUAL.PRE(5) input: number): number {
42
+ return input;
43
+ }
44
+
45
+ @DBC.ParamvalueProvider
46
+ public lessPre(@LESS.PRE(10) input: number): number {
47
+ return input;
48
+ }
49
+
50
+ @DBC.ParamvalueProvider
51
+ public lessOrEqualPre(@LESS_OR_EQUAL.PRE(10) input: number): number {
52
+ return input;
53
+ }
54
+
55
+ @DBC.ParamvalueProvider
56
+ public differentPre(@DIFFERENT.PRE("forbidden", undefined) input: string): string {
57
+ return input;
58
+ }
59
+
60
+ @DBC.ParamvalueProvider
61
+ public instancePre(@INSTANCE.PRE(Date) input: unknown): unknown {
62
+ return input;
63
+ }
64
+
65
+ @DBC.ParamvalueProvider
66
+ public aePre(@AE.PRE([new TYPE("string")]) input: unknown[]): unknown[] {
67
+ return input;
68
+ }
69
+
70
+ @DBC.ParamvalueProvider
71
+ public orPre(@OR.PRE([new EQ("a"), new EQ("b")]) input: string): string {
72
+ return input;
73
+ }
74
+ }
75
+
76
+ const subject = new PreTestSubject();
77
+
78
+ // REGEX.PRE
79
+ test("REGEX.PRE passes with matching value", () => {
80
+ expect(() => subject.regexPre("ABC")).not.toThrow();
81
+ });
82
+ test("REGEX.PRE throws on non-matching value", () => {
83
+ expect(() => subject.regexPre("abc123")).toThrow();
84
+ });
85
+
86
+ // TYPE.PRE
87
+ test("TYPE.PRE passes with correct type", () => {
88
+ expect(() => subject.typePre("hello")).not.toThrow();
89
+ });
90
+ test("TYPE.PRE throws with wrong type", () => {
91
+ expect(() => subject.typePre(42)).toThrow();
92
+ });
93
+
94
+ // EQ.PRE
95
+ test("EQ.PRE passes with equal value", () => {
96
+ expect(() => subject.eqPre("hello")).not.toThrow();
97
+ });
98
+ test("EQ.PRE throws with non-equal value", () => {
99
+ expect(() => subject.eqPre("world")).toThrow();
100
+ });
101
+
102
+ // GREATER.PRE
103
+ test("GREATER.PRE passes with value > reference", () => {
104
+ expect(() => subject.greaterPre(10)).not.toThrow();
105
+ });
106
+ test("GREATER.PRE throws with value <= reference", () => {
107
+ expect(() => subject.greaterPre(5)).toThrow();
108
+ });
109
+ test("GREATER.PRE throws with value < reference", () => {
110
+ expect(() => subject.greaterPre(3)).toThrow();
111
+ });
112
+
113
+ // GREATER_OR_EQUAL.PRE
114
+ test("GREATER_OR_EQUAL.PRE passes with value >= reference", () => {
115
+ expect(() => subject.greaterOrEqualPre(5)).not.toThrow();
116
+ });
117
+ test("GREATER_OR_EQUAL.PRE passes with value > reference", () => {
118
+ expect(() => subject.greaterOrEqualPre(10)).not.toThrow();
119
+ });
120
+ test("GREATER_OR_EQUAL.PRE throws with value < reference", () => {
121
+ expect(() => subject.greaterOrEqualPre(3)).toThrow();
122
+ });
123
+
124
+ // LESS.PRE
125
+ test("LESS.PRE passes with value < reference", () => {
126
+ expect(() => subject.lessPre(5)).not.toThrow();
127
+ });
128
+ test("LESS.PRE throws with value >= reference", () => {
129
+ expect(() => subject.lessPre(10)).toThrow();
130
+ });
131
+
132
+ // LESS_OR_EQUAL.PRE
133
+ test("LESS_OR_EQUAL.PRE passes with value <= reference", () => {
134
+ expect(() => subject.lessOrEqualPre(10)).not.toThrow();
135
+ });
136
+ test("LESS_OR_EQUAL.PRE throws with value > reference", () => {
137
+ expect(() => subject.lessOrEqualPre(15)).toThrow();
138
+ });
139
+
140
+ // DIFFERENT.PRE
141
+ test("DIFFERENT.PRE passes with different value", () => {
142
+ expect(() => subject.differentPre("allowed")).not.toThrow();
143
+ });
144
+ test("DIFFERENT.PRE throws with equal value", () => {
145
+ expect(() => subject.differentPre("forbidden")).toThrow();
146
+ });
147
+
148
+ // INSTANCE.PRE
149
+ test("INSTANCE.PRE passes with correct instance", () => {
150
+ expect(() => subject.instancePre(new Date())).not.toThrow();
151
+ });
152
+ test("INSTANCE.PRE throws with wrong instance", () => {
153
+ expect(() => subject.instancePre("not a date")).toThrow();
154
+ });
155
+
156
+ // AE.PRE
157
+ test("AE.PRE passes with all elements matching", () => {
158
+ expect(() => subject.aePre(["a", "b", "c"])).not.toThrow();
159
+ });
160
+ test("AE.PRE throws when an element does not match", () => {
161
+ expect(() => subject.aePre(["a", 42, "c"])).toThrow();
162
+ });
163
+
164
+ // OR.PRE
165
+ test("OR.PRE passes when one contract is satisfied", () => {
166
+ expect(() => subject.orPre("a")).not.toThrow();
167
+ });
168
+ test("OR.PRE throws when no contract is satisfied", () => {
169
+ expect(() => subject.orPre("c")).toThrow();
170
+ });
171
+ });
172
+
173
+ describe("Decorator: @POST (Postconditions)", () => {
174
+ class PostTestSubject {
175
+ @REGEX.POST(/^OK:.*$/)
176
+ @DBC.ParamvalueProvider
177
+ public formatResponse(@TYPE.PRE("string") input: string): string {
178
+ return `OK:${input}`;
179
+ }
180
+
181
+ @REGEX.POST(/^OK:.*$/)
182
+ public failingPost(): string {
183
+ return "FAIL";
184
+ }
185
+
186
+ @EQ.POST("hello")
187
+ public eqPost(returnThis: string): string {
188
+ return returnThis;
189
+ }
190
+ }
191
+
192
+ const subject = new PostTestSubject();
193
+
194
+ test("POST passes when return value matches", () => {
195
+ expect(() => subject.formatResponse("test")).not.toThrow();
196
+ });
197
+
198
+ test("POST throws when return value does not match", () => {
199
+ expect(() => subject.failingPost()).toThrow();
200
+ });
201
+
202
+ test("EQ.POST passes with matching return value", () => {
203
+ expect(() => subject.eqPost("hello")).not.toThrow();
204
+ });
205
+
206
+ test("EQ.POST throws with non-matching return value", () => {
207
+ expect(() => subject.eqPost("world")).toThrow();
208
+ });
209
+ });
210
+
211
+ describe("Decorator: @INVARIANT (Field contracts)", () => {
212
+ test("INVARIANT allows valid initial value", () => {
213
+ expect(() => {
214
+ class InvariantSubject {
215
+ @REGEX.INVARIANT(/^[A-Z]+$/)
216
+ public code = "ABC";
217
+ }
218
+ new InvariantSubject();
219
+ }).not.toThrow();
220
+ });
221
+
222
+ test("INVARIANT throws on invalid initial value", () => {
223
+ expect(() => {
224
+ class InvariantSubject {
225
+ @REGEX.INVARIANT(/^[A-Z]+$/)
226
+ public code = "abc123";
227
+ }
228
+ new InvariantSubject();
229
+ }).toThrow();
230
+ });
231
+
232
+ test("INVARIANT throws on invalid reassignment", () => {
233
+ class InvariantSubject {
234
+ @REGEX.INVARIANT(/^[A-Z]+$/)
235
+ public code = "ABC";
236
+ }
237
+ const obj = new InvariantSubject();
238
+ expect(() => {
239
+ obj.code = "invalid!";
240
+ }).toThrow();
241
+ });
242
+
243
+ test("INVARIANT allows valid reassignment", () => {
244
+ class InvariantSubject {
245
+ @REGEX.INVARIANT(/^[A-Z]+$/)
246
+ public code = "ABC";
247
+ }
248
+ const obj = new InvariantSubject();
249
+ expect(() => {
250
+ obj.code = "XYZ";
251
+ }).not.toThrow();
252
+ });
253
+ });
254
+
255
+ describe("Decorator: @ParamvalueProvider", () => {
256
+ test("ParamvalueProvider passes multiple parameter contracts", () => {
257
+ class MultiParam {
258
+ @DBC.ParamvalueProvider
259
+ public method(
260
+ @TYPE.PRE("string") a: string,
261
+ @TYPE.PRE("number") b: number,
262
+ ): string {
263
+ return `${a}:${b}`;
264
+ }
265
+ }
266
+ const obj = new MultiParam();
267
+ expect(() => obj.method("hello", 42)).not.toThrow();
268
+ });
269
+
270
+ test("ParamvalueProvider catches second parameter violation", () => {
271
+ class MultiParam {
272
+ @DBC.ParamvalueProvider
273
+ public method(
274
+ @TYPE.PRE("string") a: string,
275
+ @TYPE.PRE("number") b: number,
276
+ ): string {
277
+ return `${a}:${b}`;
278
+ }
279
+ }
280
+ const obj = new MultiParam();
281
+ expect(() => obj.method("hello", "not a number" as any)).toThrow();
282
+ });
283
+ });
284
+
285
+ describe("DBC infringement settings", () => {
286
+ class InfringementTest {
287
+ @DBC.ParamvalueProvider
288
+ public method(@TYPE.PRE("string") input: unknown): unknown {
289
+ return input;
290
+ }
291
+ }
292
+
293
+ test("Violations throw DBC.Infringement by default", () => {
294
+ const obj = new InfringementTest();
295
+ expect(() => obj.method(42)).toThrow(/XDBC Infringement/);
296
+ });
297
+
298
+ test("Error message includes class name, method name, and parameter info", () => {
299
+ const obj = new InfringementTest();
300
+ try {
301
+ obj.method(42);
302
+ fail("Should have thrown");
303
+ } catch (e: any) {
304
+ expect(e.message).toContain("InfringementTest");
305
+ expect(e.message).toContain("method");
306
+ expect(e.message).toContain("1st parameter");
307
+ }
308
+ });
309
+ });
310
+
311
+ describe("DBC.register()", () => {
312
+ test("registers an instance at the default path", () => {
313
+ const custom = new DBC();
314
+ DBC.register(custom);
315
+ expect((window as any).WaXCode.DBC).toBe(custom);
316
+ // Restore original
317
+ DBC.register(dbc);
318
+ });
319
+
320
+ test("registers an instance at a custom path", () => {
321
+ const custom = new DBC();
322
+ DBC.register(custom, "TestVendor.DBC");
323
+ expect((window as any).TestVendor.DBC).toBe(custom);
324
+ });
325
+
326
+ test("constructor does not auto-mount to globalThis", () => {
327
+ const original = (window as any).WaXCode.DBC;
328
+ const orphan = new DBC();
329
+ // Constructor should NOT have replaced the registered instance
330
+ expect((window as any).WaXCode.DBC).toBe(original);
331
+ expect(orphan).not.toBe(original);
332
+ });
333
+ });
334
+
335
+ describe("DBC.isolated()", () => {
336
+ test("provides a temporary DBC instance and restores the original", () => {
337
+ const original = (window as any).WaXCode.DBC;
338
+ let isolatedInstance: DBC | undefined;
339
+ DBC.isolated((tempDbc) => {
340
+ isolatedInstance = tempDbc;
341
+ expect(tempDbc).not.toBe(original);
342
+ expect((window as any).WaXCode.DBC).toBe(tempDbc);
343
+ });
344
+ // After isolated() returns, the original is restored
345
+ expect((window as any).WaXCode.DBC).toBe(original);
346
+ expect(isolatedInstance).toBeDefined();
347
+ });
348
+
349
+ test("restores original even if callback throws", () => {
350
+ const original = (window as any).WaXCode.DBC;
351
+ expect(() => {
352
+ DBC.isolated(() => {
353
+ throw new Error("test error");
354
+ });
355
+ }).toThrow("test error");
356
+ expect((window as any).WaXCode.DBC).toBe(original);
357
+ });
358
+
359
+ test("isolated instance has independent settings", () => {
360
+ DBC.isolated((tempDbc) => {
361
+ tempDbc.executionSettings.checkPreconditions = false;
362
+ expect(dbc.executionSettings.checkPreconditions).toBe(true);
363
+ });
364
+ });
365
+ });
@@ -1,4 +1,6 @@
1
- import { GREATER } from "../../src/DBC/GREATER";
1
+ import { GREATER } from "../../src/DBC/COMPARISON/GREATER";
2
+ import { GREATER_OR_EQUAL } from "../../src/DBC/COMPARISON/GREATER_OR_EQUAL";
3
+ import { LESS_OR_EQUAL } from "../../src/DBC/COMPARISON/LESS_OR_EQUAL";
2
4
 
3
5
  describe("GREATER", () => {
4
6
  const greater = new GREATER(1);
@@ -11,16 +13,16 @@ describe("GREATER", () => {
11
13
  expect(typeof greater.check(0)).toBe("string");
12
14
  });
13
15
 
14
- test("Should report infringement with '0' to check", () => {
15
- expect(typeof greater.check(0)).toBe("string");
16
+ test("Should report infringement with '1' to check (equality not permitted)", () => {
17
+ expect(typeof greater.check(1)).toBe("string");
16
18
  });
17
19
 
18
20
  test("Should not report infringement with '1' and '1' to check since equality is now permitted", () => {
19
- expect(new GREATER(1, true).check(1)).toBe(true);
21
+ expect(new GREATER_OR_EQUAL(1).check(1)).toBe(true);
20
22
  });
21
23
 
22
- test("Should not report infringement with '2' and '1' to check since inverting the result is now on", () => {
23
- expect(new GREATER(1, true, true).check(1)).toBe(true);
24
+ test("Should not report infringement with '1' and '1' to check since inverting the result is now on", () => {
25
+ expect(new LESS_OR_EQUAL(1).check(1)).toBe(true);
24
26
  });
25
27
 
26
28
  test("Should not report infringement with 'undefined' and 'undefined' to check", () => {
@@ -0,0 +1,56 @@
1
+ import { HasAttribute } from "../../src/DBC/HasAttribute";
2
+
3
+ describe("HasAttribute", () => {
4
+ const hasId = new HasAttribute("id");
5
+
6
+ test("Should not report infringement when attribute exists", () => {
7
+ const el = document.createElement("div");
8
+ el.setAttribute("id", "test");
9
+ expect(hasId.check(el)).toBe(true);
10
+ });
11
+
12
+ test("Should report infringement when attribute is missing", () => {
13
+ const el = document.createElement("div");
14
+ expect(typeof hasId.check(el)).toBe("string");
15
+ });
16
+
17
+ test("Should report infringement when value is not an HTMLElement", () => {
18
+ expect(typeof hasId.check("not an element")).toBe("string");
19
+ });
20
+
21
+ test("Should report infringement when value is a plain object", () => {
22
+ expect(typeof hasId.check({ id: "test" })).toBe("string");
23
+ });
24
+
25
+ describe("invert", () => {
26
+ const noId = new HasAttribute("id", true);
27
+
28
+ test("Should not report infringement when attribute is absent", () => {
29
+ const el = document.createElement("div");
30
+ expect(noId.check(el)).toBe(true);
31
+ });
32
+
33
+ test("Should report infringement when forbidden attribute exists", () => {
34
+ const el = document.createElement("div");
35
+ el.setAttribute("id", "test");
36
+ expect(typeof noId.check(el)).toBe("string");
37
+ });
38
+ });
39
+
40
+ describe("checkAlgorithm", () => {
41
+ test("Should return true when element has the attribute", () => {
42
+ const el = document.createElement("span");
43
+ el.setAttribute("class", "active");
44
+ expect(HasAttribute.checkAlgorithm(el, "class", false)).toBe(true);
45
+ });
46
+
47
+ test("Should return string when element lacks the attribute", () => {
48
+ const el = document.createElement("span");
49
+ expect(typeof HasAttribute.checkAlgorithm(el, "class", false)).toBe("string");
50
+ });
51
+
52
+ test("Should return string for non-HTMLElement", () => {
53
+ expect(typeof HasAttribute.checkAlgorithm(42, "id", false)).toBe("string");
54
+ });
55
+ });
56
+ });