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/CONTRIBUTING.md CHANGED
@@ -1,40 +1,152 @@
1
1
  # Contributing to XDBC
2
2
 
3
- Thank you for your interest in contributing to XDBC! We welcome contributions of all kinds, including bug reports, feature requests, code contributions, and documentation improvements.
3
+ Thank you for your interest in contributing to XDBC. Contributions of all kinds are welcome — bug reports, feature requests, code improvements, documentation enhancements, and test coverage expansion.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Getting Started](#getting-started)
10
+ - [Reporting Issues](#reporting-issues)
11
+ - [Contributing Code](#contributing-code)
12
+ - [Development Workflow](#development-workflow)
13
+ - [Code Style](#code-style)
14
+ - [Testing](#testing)
15
+ - [Documentation](#documentation)
16
+ - [License Agreement](#license-agreement)
17
+ - [Code of Conduct](#code-of-conduct)
18
+ - [Contact](#contact)
19
+
20
+ ---
21
+
22
+ ## Getting Started
23
+
24
+ 1. **Fork** the repository on GitHub.
25
+ 2. **Clone** your fork locally:
26
+ ```sh
27
+ git clone https://github.com/<your-username>/XDBC.git
28
+ cd XDBC
29
+ ```
30
+ 3. **Install dependencies**:
31
+ ```sh
32
+ npm install
33
+ ```
34
+ 4. **Run the test suite** to verify the setup:
35
+ ```sh
36
+ npm test
37
+ ```
38
+
39
+ ---
4
40
 
5
41
  ## Reporting Issues
6
42
 
7
- If you find a bug or have a feature request, please open an issue on GitHub. When reporting a bug, please include:
43
+ If you encounter a bug or have a feature request, please [open an issue](https://github.com/CallariS/XDBC/issues/new) on GitHub.
8
44
 
9
- * Steps to reproduce the bug
10
- * Expected behavior
11
- * Actual behavior
12
- * Your operating system and browser (if applicable)
45
+ When reporting a bug, include:
46
+
47
+ - A clear, descriptive title
48
+ - Steps to reproduce the issue
49
+ - Expected behavior vs. actual behavior
50
+ - Environment details (Node.js version, TypeScript version, OS)
51
+ - A minimal code sample or test case, if possible
52
+
53
+ For feature requests, describe the use case and how the proposed change benefits users.
54
+
55
+ ---
13
56
 
14
57
  ## Contributing Code
15
58
 
16
- 1. Fork the repository.
17
- 2. Create a branch for your changes: `git checkout -b my-feature-branch`.
18
- 3. Make your changes and commit them: `git commit -am 'Add some feature'`.
19
- 4. Push your changes to your fork: `git push origin my-feature-branch`.
20
- 5. Open a pull request on GitHub.
59
+ ### Branch Strategy
60
+
61
+ - Create a feature branch from `master`:
62
+ ```sh
63
+ git checkout -b feature/my-improvement
64
+ ```
65
+ - Use descriptive branch names: `feature/`, `fix/`, `docs/`, `test/`
66
+
67
+ ### Commit Guidelines
68
+
69
+ - Write clear, concise commit messages in imperative mood:
70
+ - **Good**: `Add RANGE contract for numeric boundaries`
71
+ - **Avoid**: `Added stuff`, `WIP`, `fix`
72
+ - Each commit should represent a single logical change
73
+ - Reference related issues where applicable: `Fix #12 — handle null in OR.check()`
74
+
75
+ ### Pull Request Process
76
+
77
+ 1. Ensure your branch is up to date with `master`
78
+ 2. Run the full test suite and linter before submitting
79
+ 3. Open a pull request with:
80
+ - A description of what the change does and why
81
+ - Links to related issues
82
+ - Any breaking changes clearly noted
83
+ 4. Address review feedback promptly
84
+ 5. A maintainer will merge once the PR is approved
85
+
86
+ ---
87
+
88
+ ## Development Workflow
89
+
90
+ | Command | Purpose |
91
+ |---|---|
92
+ | `npm test` | Run the test suite (Jest) |
93
+ | `npm run build` | Build the project (Webpack) |
94
+ | `npm run lint` | Lint the codebase (Biome) |
95
+ | `npm run format` | Auto-format source files (Biome) |
96
+ | `npm run docs` | Generate API documentation (TypeDoc) |
97
+
98
+ ---
21
99
 
22
100
  ## Code Style
23
101
 
24
- Please follow the coding style guidelines used in the project. We use Biome, so please run it before submitting a pull request.
102
+ - **TypeScript** is the primary language. All source code resides in `src/`.
103
+ - **Biome** is used for both linting and formatting. Run `npm run lint` and `npm run format` before submitting.
104
+ - Follow existing patterns:
105
+ - Each contract class lives in its own file under `src/DBC/`
106
+ - Derived contracts go in subdirectories (e.g., `src/DBC/COMPARISON/`)
107
+ - Every contract exposes `PRE`, `POST`, and `INVARIANT` static decorator factories
108
+ - Avoid introducing new dependencies unless absolutely necessary
109
+ - Prefer strict types over `any` where feasible
110
+
111
+ ---
112
+
113
+ ## Testing
114
+
115
+ - Tests are located in `__tests__/DBC/` and use **Jest** with `ts-jest`
116
+ - Every new contract or behavioral change should include corresponding tests
117
+ - Test file naming convention: `<ContractName>.test.ts`
118
+ - Run the suite with:
119
+ ```sh
120
+ npm test
121
+ ```
122
+ - Aim for tests that cover:
123
+ - `check()` method behavior (passing and failing cases)
124
+ - Decorator execution (`PRE`, `POST`, `INVARIANT`) where applicable
125
+ - Edge cases (null, undefined, empty arrays, wrong types)
126
+
127
+ ---
25
128
 
26
129
  ## Documentation
27
130
 
28
- We welcome improvements to the documentation. Please submit pull requests with your changes.
131
+ - API documentation is generated with [TypeDoc](https://typedoc.org/) (`npm run docs`)
132
+ - Use JSDoc-style comments on all public classes, methods, and parameters
133
+ - Update the README if your change adds new contracts, features, or configuration options
134
+ - Keep `Demo.ts` up to date with representative usage examples
29
135
 
30
- ## License
136
+ ---
31
137
 
32
- By contributing to XDBC, you agree that your contributions will be licensed under the MIT license.
138
+ ## License Agreement
139
+
140
+ By contributing to XDBC, you agree that your contributions will be licensed under the [MIT License](LICENSE).
141
+
142
+ ---
33
143
 
34
144
  ## Code of Conduct
35
145
 
36
- Please review and abide by our [Code of Conduct](CODE_OF_CONDUCT.md).
146
+ All contributors must adhere to the [Code of Conduct](CODE_OF_CONDUCT.md). Respectful, professional interaction is expected in all project spaces.
147
+
148
+ ---
37
149
 
38
150
  ## Contact
39
151
 
40
- If you have any questions, please mail to [XDBC@WaXcode.net](mailto:XDBC@WaXCode.net).
152
+ For questions about contributing, reach out at [XDBC@WaXCode.net](mailto:XDBC@WaXCode.net).
package/README.md CHANGED
@@ -1,103 +1,405 @@
1
- # XDbC / e**X**plicit **D**esign **b**y **C**ontract™
1
+ <p align="center">
2
+ <img src="https://img.shields.io/npm/v/xdbc?style=flat-square" alt="npm version" />
3
+ <img src="https://img.shields.io/npm/l/xdbc?style=flat-square" alt="license" />
4
+ <img src="https://img.shields.io/npm/dt/xdbc?style=flat-square" alt="downloads" />
5
+ <img src="https://img.shields.io/badge/TypeScript-5.x-blue?style=flat-square&logo=typescript" alt="TypeScript" />
6
+ <img src="https://img.shields.io/badge/decorators-stage%203-green?style=flat-square" alt="decorators" />
7
+ </p>
2
8
 
3
- Leverages the explicit nature of metadata to provide a **D**esign **b**y **C**ontract Framework in a precise and comprehensible manner.
9
+ # XDBC e**X**plicit **D**esign **b**y **C**ontract for TypeScript
4
10
 
5
- | Do... | Instead Of |
6
- |-------------------|------------------------------------------------------------|
7
- | <pre>@DBC.ParamvalueProvider<br>public method(@AE.PRE([new REGEX(/^\.*XDBC.\*$/i)]) input : Array\<string>) {<br> ... <br>}</pre>|<pre>public method( input : Array\<string>) {<br> input.forEach(( element, index ) => {<br> console.assert(/^.\*XDBC.\*$/i.test(element),"inconsistent error message");<br> });<br><br> ...<br>}</pre>
8
- | <pre>@REGEX.INVARIANT(/^.\*XDBC.\*$/i)<br>public field = "XDBC";</pre>|<pre>get field() : string { return ... }<br>set field( toSet : string ) {<br> console.assert(/^.\*XDBC.\*$/i.test(element),"Inconsistent error message"); <br><br> ...<br>}</pre>
9
- | <pre>@REGEX.POST(/^XDBC$/i)<br>public method( input : unknown ) : string {<br> ...<br><br> return result ;<br>}</pre>|<pre>public method( input : unknown ) : string {<br> ...<br><br> if(!/^.\*XDBC.\*$/i.test(result) {<br> throw new Error("inconsistent error message");<br> }<br><br> return result ;<br>}</pre>
10
- <pre>...and get consistent details about errors like: <code style = "background-color : beige ; color : red ;">[ XDBC Infringement [ From "method" in "MyClass": [ Parameter-value "+1d,+5d,-x10y" of the 1st parameter did not fulfill one of it's contracts: Violating-Arrayelement at index 2. Value has to comply to regular expression "/^(?i:(NOW)|([+-]\d+[dmy]))$/i"]]]</code></pre>
11
+ > A decorator-based Design by Contract framework that enforces preconditions, postconditions, and invariants through TypeScript metadata — delivering precise, self-documenting, and verifiable component contracts.
11
12
 
12
- ## What is **D**esign **b**y **C**ontract™ ?
13
- [**D**esign **b**y **C**ontract™ (DbC)](https://en.wikipedia.org/wiki/Design_by_contract) is a software development approach focused on defining precise and verifiable contracts between software components. These contracts specify the preconditions that must be true when calling a component (e.g., a function or method), the postconditions guaranteed after the component's execution, and the invariants that must hold true throughout the lifetime of an object or class.
13
+ ---
14
14
 
15
- ## Benefits of Design by Contract:
15
+ ## At a Glance
16
16
 
17
- | Benefit | Description |
18
- |-----------------------|------------------------------------------------------------|
19
- | More Reliable | Early error detection through contract checking |
20
- | More Maintainable | Clear responsibilities and expected behavior |
21
- | Better Documentation | Contracts as living behavior descriptions |
22
- | Easier Debugging | Error causes traceable through contract violations |
17
+ | Approach | With XDBC | Without XDBC |
18
+ |---|---|---|
19
+ | **Parameter validation** | <pre>@DBC.ParamvalueProvider<br>method(@REGEX.PRE(/^\.*XDBC.\*$/i) input: string[]) {<br> ...<br>}</pre> | <pre>method(input: string[]) {<br> input.forEach((el, i) => {<br> console.assert(/^.\*XDBC.\*$/i.test(el), "error");<br> });<br> ...<br>}</pre> |
20
+ | **Field invariant** | <pre>@REGEX.INVARIANT(/^.\*XDBC.\*$/i)<br>public field = "XDBC";</pre> | <pre>get field(): string { return this._field; }<br>set field(v: string) {<br> console.assert(/^.\*XDBC.\*$/i.test(v), "error");<br> this._field = v;<br>}</pre> |
21
+ | **Return validation** | <pre>@REGEX.POST(/^XDBC$/i)<br>method(input: unknown): string {<br> ...<br> return result;<br>}</pre> | <pre>method(input: unknown): string {<br> ...<br> if (!/^XDBC$/i.test(result)) {<br> throw new Error("error");<br> }<br> return result;<br>}</pre> |
23
22
 
23
+ Contract violations produce structured, actionable diagnostics:
24
24
 
25
- **DbC** improves software quality and maintainability by explicitly defining and verifying contract conditions.
25
+ ```
26
+ [ XDBC Infringement [ From "method" in "MyClass": [ Parameter-value "+1d,+5d,-x10y"
27
+ of the 1st parameter did not fulfill one of it's contracts: Violating-Arrayelement at
28
+ index 2. Value has to comply to regular expression "/^(?i:(NOW)|([+-]\d+[dmy]))$/i"]]]
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Table of Contents
34
+
35
+ - [What is Design by Contract?](#what-is-design-by-contract)
36
+ - [Why XDBC?](#why-xdbc)
37
+ - [Installation](#installation)
38
+ - [Quick Start](#quick-start)
39
+ - [Contracts Reference](#contracts-reference)
40
+ - [Core Concepts](#core-concepts)
41
+ - [Advanced Features](#advanced-features)
42
+ - [Configuration](#configuration)
43
+ - [API Documentation](#api-documentation)
44
+ - [Contributing](#contributing)
45
+ - [License](#license)
46
+
47
+ ---
48
+
49
+ ## What is Design by Contract?
26
50
 
27
- ## What is the difference between DbC and Assertions ?
51
+ [Design by Contract (DbC)](https://en.wikipedia.org/wiki/Design_by_contract) is a software engineering methodology that defines formal, precise, and verifiable interface specifications for software components. Each component's contract comprises:
28
52
 
29
- | Feature | DBC with Decorators | Assertions |
30
- |------------------|----------------------------------------|---------------------------------------|
31
- | Formality | Formal, explicit in definition | Informal, often within the body |
32
- | Integration | Metadata | Built-in keyword |
33
- | Features | Can be more feature-rich | Simple, primarily for error detection |
34
- | Readability | Generally good, contracts are clear | Can become cluttered |
35
- | Maintainability | Often better, contracts are localized | Can be harder to track and modify |
36
- | Production | Contracts can be kept or disabled | Often disabled for performance |
53
+ | Element | Purpose |
54
+ |---|---|
55
+ | **Preconditions** | Conditions that must hold true *before* a method executes |
56
+ | **Postconditions** | Guarantees that must hold true *after* a method returns |
57
+ | **Invariants** | Properties that must remain true *throughout* an object's lifetime |
37
58
 
38
- ## Demo & API Documentation
39
- Check out the **Demo.ts** to see some examples usages and the [API](https://callaris.github.io/XDBC/)'s documentation.
59
+ ### DbC vs. Assertions
60
+
61
+ | Aspect | XDBC Decorators | Manual Assertions |
62
+ |---|---|---|
63
+ | Formality | Formal, declarative, co-located with signatures | Informal, scattered through method bodies |
64
+ | Integration | TypeScript metadata and decorators | Built-in `console.assert` / `throw` |
65
+ | Expressiveness | Composable, parameterized contract objects | Simple boolean checks |
66
+ | Readability | Contracts are visible at the API surface | Validation logic obscures business logic |
67
+ | Maintainability | Contracts are localized and reusable | Duplicated checks are hard to track |
68
+ | Production control | Selectively enable/disable by contract type | Typically all-or-nothing |
69
+
70
+ ---
71
+
72
+ ## Why XDBC?
73
+
74
+ - **Declarative** — contracts live as decorators alongside type signatures, not buried in method bodies
75
+ - **Composable** — combine contracts with `AE`, `OR`, and `IF` for expressive validation
76
+ - **Configurable** — toggle preconditions, postconditions, and invariants independently
77
+ - **Diagnostic** — structured error messages pinpoint the exact violation, parameter, and context
78
+ - **Extensible** — 16 built-in contracts, with support for custom contracts and Zod schema integration
79
+ - **Zero runtime overhead** — disable contract checking in production with a single flag
80
+
81
+ ---
40
82
 
41
83
  ## Installation
42
84
 
43
85
  ```sh
44
- npm install --save xdbc
86
+ npm install xdbc
87
+ ```
88
+
89
+ **Requirements:** TypeScript 5.x with `experimentalDecorators` and `emitDecoratorMetadata` enabled in `tsconfig.json`.
90
+
91
+ ```jsonc
92
+ // tsconfig.json
93
+ {
94
+ "compilerOptions": {
95
+ "experimentalDecorators": true,
96
+ "emitDecoratorMetadata": true
97
+ }
98
+ }
45
99
  ```
46
100
 
47
- ## Usage
101
+ ---
102
+
103
+ ## Quick Start
104
+
105
+ ```typescript
106
+ import { DBC, REGEX, TYPE, EQ } from "xdbc";
107
+
108
+ class UserService {
109
+
110
+ // Invariant: email must always match pattern
111
+ @REGEX.INVARIANT(/^[^@]+@[^@]+\.[^@]+$/)
112
+ public email = "user@example.com";
113
+
114
+ // Precondition: name must be a string; Postcondition: return must match pattern
115
+ @REGEX.POST(/^Hello, .+$/)
116
+ @DBC.ParamvalueProvider
117
+ public greet(@TYPE.PRE("string") name: string): string {
118
+ return `Hello, ${name}`;
119
+ }
120
+
121
+ // Precondition: age must be >= 0
122
+ @DBC.ParamvalueProvider
123
+ public setAge(@GREATER_OR_EQUAL.PRE(0) age: number) {
124
+ // ...
125
+ }
126
+ }
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Contracts Reference
132
+
133
+ XDBC ships with **16 contracts** organized into core validators and derived specializations:
134
+
135
+ ### Core Contracts
48
136
 
49
- As by now there're 14 contracts that can be used:
137
+ | Contract | Description | Constructor |
138
+ |---|---|---|
139
+ | **`REGEX`** | Value must match a regular expression | `new REGEX(expression: RegExp)` |
140
+ | **`TYPE`** | Value must be of a specified type (supports pipe-separated: `"string\|number"`) | `new TYPE(type: string)` |
141
+ | **`EQ`** | Value must equal (or not equal) a reference value | `new EQ(equivalent: any, invert?: boolean)` |
142
+ | **`COMPARISON`** | Numeric comparison against a reference value | `new COMPARISON(equivalent, equalityPermitted, invert)` |
143
+ | **`INSTANCE`** | Value must be an instance of a specified class | `new INSTANCE(reference: any \| any[])` |
144
+ | **`AE`** | Every element in an array must satisfy a set of contracts | `new AE(conditions, index?, idxEnd?)` |
145
+ | **`OR`** | At least one of a set of contracts must be satisfied | `new OR(conditions: DBC[])` |
146
+ | **`IF`** | Conditional contract: if A holds, then B must also hold | `IF.PRE(condition, inCase, path?, invert?)` |
147
+ | **`JSON_OP`** | Object must contain specific properties of specific types | `new JSON_OP(properties: {name, type}[], checkElements?)` |
148
+ | **`JSON_Parse`** | String must be valid JSON; optionally forwards parsed result | `new JSON_Parse(receptor?: (json) => void)` |
149
+ | **`DEFINED`** | Value must not be `null` or `undefined` | — |
150
+ | **`UNDEFINED`** | Value must be `undefined` | — |
151
+ | **`HasAttribute`** | HTMLElement must possess a named attribute | `HasAttribute.PRE(attrName, invert?)` |
152
+ | **`ZOD`** | Value must validate against a Zod schema | `new ZOD(schema: z.ZodType)` |
50
153
 
51
- - AE (*Each element of the value-array has to fulfill a certain set of contracts*)
52
- - EQ (*Value has to be equal to a supplied reference value*)
53
- - COMPARISON (*Value has to be greater, less, greater/equal, equal or less/equal than a supplied reference value*)
54
- - INSTANCE (*Value has to be an instance of a supplied type*)
55
- - JSON.OP (*Value has to contain certain properties of certain type*)
56
- - JSON.Parse (*String-value has to be a parsable JSON*)
57
- - OR (*At least one of a set of contracts has to be fulfilled*)
58
- - REGEX (*Value has to be validated by a supplied regular expression*)
59
- - TYPE (*Value has to be of a certain type*)
60
- - GREATER (*Derived from COMPARISON*)
61
- - GREATER_OR_EQUAL (*Derived from COMPARISON*)
62
- - LESS (*Derived from COMPARISON*)
63
- - LESS_OR_EQUAL (*Derived from COMPARISON*)
64
- - DIFFERENT (*Derived from EQ*)
154
+ ### Derived Contracts
65
155
 
66
- All of which expose a method **PRE**, **POST** and **INVARIANT** (*precondition, postcondition and invariant*).<br>
67
- Import the classes to use from **xdbc**. If parameters shall be decorated with contracts import class **DBC** also. <br><br>
156
+ | Contract | Derives From | Semantics |
157
+ |---|---|---|
158
+ | **`GREATER`** | `COMPARISON` | `value > reference` |
159
+ | **`GREATER_OR_EQUAL`** | `COMPARISON` | `value >= reference` |
160
+ | **`LESS`** | `COMPARISON` | `value < reference` |
161
+ | **`LESS_OR_EQUAL`** | `COMPARISON` | `value <= reference` |
162
+ | **`DIFFERENT`** | `EQ` | `value !== reference` |
68
163
 
69
- The **PRE**-Method can be used to decorate method-parameter: <code>public method(@REGEX.PRE(/XDBC.\*/g) input : string)</code>.<br>Whenever the method is invoked the value will be checked. Since parameter decorators don't have access to the parameter's value, the method itself must additionally be decorated with the **ParamvalueProvider**:<br>
70
- <code>
71
- @DBC.**ParamvalueProvider**<br>
72
- public method(@REGEX.PRE(/XDBC.\*/g) input : string)
73
- </code><br><br>
74
- The **POST**-Method can be used to decorate a method:<br>
75
- <code>
76
- @EQ.POST(10)<br>
77
- public method() { return 10 ;}<br></code>
78
- Whenever the method returns, it's return-value will be checked.<br>
164
+ ### Built-in Regular Expressions
79
165
 
80
- The **INVARIANT**-Method can be used to decorate fields:<br>
81
- <code>
82
- @REGEX.INVARIANT(/^a$/)<br>
83
- public testProperty = "a";
84
- </code><br>
85
- Whenever the field is assigned a value and also when initialized, the new value will be checked. So there's no need to write a getter and setter just because there's is the necessity to perform checks on the value anymore.<br>
166
+ `REGEX.stdExp` provides ready-to-use patterns:
86
167
 
87
- Certain contracts take other contracts as a parameter. For example the **AE** contract that applies a specified set of contracts on each element of the tagged object's value if it is an array or the object itself if it isn't: <code>@AE.PRE([new REGEX(/^(?i:(NOW)|([+-]\d+[dmy]))$/i, new GREATER(10,"length")])</code>.
168
+ | Key | Validates |
169
+ |---|---|
170
+ | `htmlAttributeName` | HTML attribute names |
171
+ | `eMail` | Email addresses |
172
+ | `property` | Property identifiers |
173
+ | `url` | URLs |
174
+ | `keyPath` | Key paths |
175
+ | `date` | Date strings |
176
+ | `dateFormat` | Date format patterns |
177
+ | `cssSelector` | CSS selectors |
178
+ | `boolean` | Boolean string literals |
179
+ | `colorCodeHEX` | Hex color codes |
180
+ | `simpleHotkey` | Keyboard shortcuts |
181
+ | `bcp47` | BCP 47 language tags |
88
182
 
89
- With **PRE**, **POST** and **INVARIANT** decorators an optional **path** parameter may be specified. This parameter is a dotted path to a nested property of the tagged object that shall be checked instead of the tagged one. Thus **@DBC.INVARIANT([new REGEX(/^.$/)])** could also be defined as: **@DBC.INVARIANT([new EQ(1)],"length")**, that way demanding that the value to be set is a string with exactly one character.
183
+ ---
90
184
 
91
- Multiple instances of the class **DBC** with varying settings for e.g. reporting infringements may be instantiated. Which of these instances is used to report can be defined when either using **PRE**, **POST** or **INVARIANT** by defining their **dbc** parameter: **@DBC.INVARIANT([new EQ(1)],"length","MyVendor.MyDBCInstance")**, for example. The standard path (*WaXCode.DBC*) leads to an automatically created instance, that is generated when the Framework is imported.
185
+ ## Core Concepts
92
186
 
93
- Many contracts got further features like the **AE**-Contract that can check specific ranges within the tagged array or the **EQ**--Contract that can be inverted turning it into **not EQual**-Contract. Check out the [API](https://callaris.github.io/XDBC/) for details.
187
+ ### Decorator Types
94
188
 
95
- A **DBC**'s **warningSettings** & **infringementSettings** determine what happens on warnings and errors, whereas warnings are not implemented yet.
189
+ Every contract exposes three decorator factories:
96
190
 
97
- **DBC** can be turned off for **PRE**-, **POST**-Conditions and **INVARIANT**S separately by setting the proper **executionSettings** of the **DBC**-Class.
191
+ | Decorator | Applies To | Validates |
192
+ |---|---|---|
193
+ | `Contract.PRE(...)` | Method parameters | Input values before method execution |
194
+ | `Contract.POST(...)` | Methods | Return value after method execution |
195
+ | `Contract.INVARIANT(...)` | Fields / Properties | Value on every assignment (including initialization) |
196
+
197
+ ### The `ParamvalueProvider` Decorator
198
+
199
+ TypeScript parameter decorators do not natively receive parameter values. Any method using `PRE` parameter contracts **must** be decorated with `@DBC.ParamvalueProvider`:
200
+
201
+ ```typescript
202
+ @DBC.ParamvalueProvider
203
+ public process(
204
+ @TYPE.PRE("string") name: string,
205
+ @REGEX.PRE(/^\d{4}$/) code: string
206
+ ) { ... }
207
+ ```
208
+
209
+ ### Path Resolution
210
+
211
+ All `PRE`, `POST`, and `INVARIANT` decorators accept an optional **`path`** parameter — a dotted path that specifies a nested property of the value to validate instead of the value itself:
212
+
213
+ ```typescript
214
+ // Validate that element.tagName === "SELECT"
215
+ @DBC.ParamvalueProvider
216
+ public handleElement(@EQ.PRE("SELECT", false, "tagName") el: HTMLElement) { }
217
+
218
+ // Validate that value.length === 1
219
+ @EQ.INVARIANT(1, false, "length")
220
+ public singleChar = "X";
221
+ ```
222
+
223
+ Path resolution supports:
224
+ - **Dot notation**: `"user.address.city"`
225
+ - **Array indices**: `"items[0]"`
226
+ - **Method calls**: `"getName()"`
227
+ - **HTML attributes**: `"@data-id"`
228
+
229
+ ### Custom Hints
230
+
231
+ Add context to error messages with the optional **`hint`** parameter:
232
+
233
+ ```typescript
234
+ @DBC.ParamvalueProvider
235
+ public setAge(
236
+ @GREATER_OR_EQUAL.PRE(0, undefined, "Age must be non-negative") age: number
237
+ ) { }
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Advanced Features
243
+
244
+ ### Composing Contracts with `AE`
245
+
246
+ Validate array elements against one or more contracts, optionally targeting a specific index range:
247
+
248
+ ```typescript
249
+ // All elements must be non-empty strings matching a date pattern
250
+ @AE.PRE([new TYPE("string"), new REGEX(/^\d{4}-\d{2}-\d{2}$/)])
251
+ public processDates(dates: string[]) { }
252
+
253
+ // Only elements at indices 1 through 3
254
+ @AE.PRE([new REGEX(/^[A-Z]+$/)], 1, 3)
255
+ public processRange(items: string[]) { }
256
+
257
+ // Single element at index 0
258
+ @AE.PRE([new TYPE("number")], 0)
259
+ public processFirst(values: unknown[]) { }
260
+ ```
261
+
262
+ ### Logical Composition with `OR`
263
+
264
+ At least one contract must pass:
265
+
266
+ ```typescript
267
+ @DBC.ParamvalueProvider
268
+ public setStatus(@OR.PRE([new EQ("active"), new EQ("inactive"), new EQ("pending")]) status: string) { }
269
+ ```
270
+
271
+ ### Conditional Contracts with `IF`
272
+
273
+ Apply a contract only when a precondition holds:
274
+
275
+ ```typescript
276
+ // If the value is a string, it must also match digits-only
277
+ @IF.PRE(new TYPE("string"), new REGEX(/^\d+$/))
278
+ public processInput(value: unknown) { }
279
+ ```
280
+
281
+ ### Zod Schema Integration
282
+
283
+ Leverage Zod schemas for complex structural validation:
284
+
285
+ ```typescript
286
+ import { z } from "zod";
287
+
288
+ const UserSchema = z.object({
289
+ name: z.string().min(1),
290
+ email: z.string().email(),
291
+ age: z.number().int().positive()
292
+ });
293
+
294
+ @DBC.ParamvalueProvider
295
+ public createUser( @ZOD.PRE(UserSchema) data: unknown) { }
296
+ ```
297
+
298
+ ### Type-Safe Static Checks
299
+
300
+ Several contracts offer static `tsCheck` methods for imperative validation outside of decorators:
301
+
302
+ ```typescript
303
+ // Throws if value is not a string
304
+ const name = TYPE.tsCheck<string>(input, "string", "Expected a string");
305
+
306
+ // Throws if value doesn't match regex
307
+ const code = REGEX.tsCheck<string>(input, /^\d{4}$/, "Invalid code format");
308
+
309
+ // Throws if not an instance of Date
310
+ const date = INSTANCE.tsCheck<Date>(input, Date, "Expected a Date");
311
+
312
+ // Throws if none of the conditions pass
313
+ const result = OR.tsCheck<string>(input, [new EQ("a"), new EQ("b")]);
314
+ ```
315
+
316
+ ---
317
+
318
+ ## Configuration
319
+
320
+ ### DBC Instance Settings
321
+
322
+ A default DBC instance is automatically registered at `WaXCode.DBC` when the module is imported. You can access and configure it:
323
+
324
+ ```typescript
325
+ import { DBC } from "xdbc";
326
+
327
+ // Access the default DBC instance
328
+ const dbc = (globalThis as any).WaXCode.DBC as DBC;
329
+
330
+ // Toggle contract checking
331
+ dbc.executionSettings.checkPreconditions = true;
332
+ dbc.executionSettings.checkPostconditions = true;
333
+ dbc.executionSettings.checkInvariants = true;
334
+
335
+ // Configure infringement handling
336
+ dbc.infringementSettings.throwException = true; // throw DBC.Infringement on violation
337
+ dbc.infringementSettings.logToConsole = false; // log to console instead
338
+ ```
339
+
340
+ ### Multiple DBC Instances
341
+
342
+ Create isolated DBC instances with separate configurations using `DBC.register()`:
343
+
344
+ ```typescript
345
+ // Register a vendor-specific instance at a custom path
346
+ const vendorDbc = new DBC(
347
+ { throwException: false, logToConsole: true },
348
+ );
349
+ DBC.register(vendorDbc, "MyVendor.DBC");
350
+
351
+ // Route a contract to the custom instance via its path
352
+ @REGEX.INVARIANT(/^[A-Z]+$/, undefined, undefined, "MyVendor.DBC")
353
+ public code = "ABC";
354
+ ```
355
+
356
+ > **Note:** `new DBC()` does not automatically mount onto `globalThis`. Call `DBC.register(instance, path)` to make an instance available for decorator resolution.
357
+
358
+ ### Test Isolation
359
+
360
+ Use `DBC.isolated()` to run tests with a temporary DBC instance that doesn't affect other tests:
361
+
362
+ ```typescript
363
+ DBC.isolated((tempDbc) => {
364
+ // tempDbc is registered at "WaXCode.DBC" for the duration of this callback
365
+ tempDbc.executionSettings.checkPreconditions = false;
366
+
367
+ // ... run tests with contracts disabled ...
368
+ });
369
+ // Original DBC instance is automatically restored here
370
+ ```
371
+
372
+ ### Disabling Contracts in Production
373
+
374
+ ```typescript
375
+ const dbc = (globalThis as any).WaXCode.DBC as DBC;
376
+ dbc.executionSettings.checkPreconditions = false;
377
+ dbc.executionSettings.checkPostconditions = false;
378
+ dbc.executionSettings.checkInvariants = false;
379
+ ```
380
+
381
+ ---
382
+
383
+ ## API Documentation
384
+
385
+ Full generated API documentation is available at **[callaris.github.io/XDBC](https://callaris.github.io/XDBC/)**.
386
+
387
+ See [`Demo.ts`](src/Demo.ts) for annotated usage examples.
388
+
389
+ ---
390
+
391
+ ## Contributing
98
392
 
99
- ## Contribution
100
393
  Participation is highly valued and warmly welcomed. The ultimate goal is to create a tool that proves genuinely useful and empowers a wide range of developers to build more robust and reliable applications.
101
394
 
395
+ Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines, and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for community standards.
396
+
397
+ ---
398
+
399
+ ## License
400
+
401
+ [MIT](LICENSE) © Callari, Salvatore
102
402
 
403
+ ---
103
404
 
405
+ <sub>"Design by Contract" is a registered trademark of Eiffel Software. XDBC is an independent project and is not affiliated with or endorsed by Eiffel Software.</sub>