xdbc 1.0.217 → 1.0.219
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.
- package/.gitattributes +16 -8
- package/.vscode/settings.json +3 -3
- package/.vscode/tasks.json +23 -23
- package/ASSESSMENT.md +249 -0
- package/README.md +538 -408
- package/__tests__/DBC/AE.test.ts +62 -62
- package/__tests__/DBC/ARRAY.test.ts +91 -91
- package/__tests__/DBC/DEFINED.test.ts +53 -53
- package/__tests__/DBC/DOM.test.ts +786 -0
- package/__tests__/DBC/Decorators.test.ts +367 -367
- package/__tests__/DBC/EQ.test.ts +13 -13
- package/__tests__/DBC/GREATER.test.ts +31 -31
- package/__tests__/DBC/HasAttribute.test.ts +60 -60
- package/__tests__/DBC/IF.test.ts +62 -62
- package/__tests__/DBC/INSTANCE.test.ts +13 -13
- package/__tests__/DBC/JSON.OP.test.ts +47 -47
- package/__tests__/DBC/JSON.Parse.test.ts +17 -17
- package/__tests__/DBC/OR.test.ts +14 -14
- package/__tests__/DBC/PLAIN_OBJECT.test.ts +109 -109
- package/__tests__/DBC/REGEX.test.ts +17 -17
- package/__tests__/DBC/TYPE.test.ts +13 -13
- package/__tests__/DBC/UNDEFINED.test.ts +45 -45
- package/__tests__/DBC/ZOD.test.ts +54 -54
- package/__tests__/DBC/onInfringement.test.ts +262 -0
- package/biome.json +45 -40
- package/dist/DBC/AE.js +172 -0
- package/dist/DBC/ARR/PLAIN_OBJECT.d.ts +0 -3
- package/dist/DBC/ARR/PLAIN_OBJECT.js +95 -0
- package/dist/DBC/ARRAY.d.ts +0 -3
- package/dist/DBC/ARRAY.js +90 -0
- package/dist/DBC/COMPARISON/GREATER.js +21 -0
- package/dist/DBC/COMPARISON/GREATER_OR_EQUAL.js +21 -0
- package/dist/DBC/COMPARISON/LESS.js +21 -0
- package/dist/DBC/COMPARISON/LESS_OR_EQUAL.js +21 -0
- package/dist/DBC/COMPARISON.js +98 -0
- package/dist/DBC/DEFINED.js +87 -0
- package/dist/DBC/DOM.d.ts +123 -0
- package/dist/DBC/DOM.js +362 -0
- package/dist/DBC/EQ/DIFFERENT.js +34 -0
- package/dist/DBC/EQ.js +101 -0
- package/dist/DBC/GREATER.js +99 -0
- package/dist/DBC/HasAttribute.js +101 -0
- package/dist/DBC/IF.js +96 -0
- package/dist/DBC/INSTANCE.js +122 -0
- package/dist/DBC/JSON.OP.js +120 -0
- package/dist/DBC/JSON.Parse.js +104 -0
- package/dist/DBC/OR.js +125 -0
- package/dist/DBC/REGEX.js +136 -0
- package/dist/DBC/TYPE.js +112 -0
- package/dist/DBC/UNDEFINED.js +87 -0
- package/dist/DBC/ZOD.js +99 -0
- package/dist/DBC.d.ts +18 -4
- package/dist/DBC.js +645 -0
- package/dist/Demo.d.ts +10 -0
- package/dist/Demo.js +713 -0
- package/dist/Test.html +18 -0
- package/dist/bundle.js +6140 -405
- package/dist/index.d.ts +22 -0
- package/dist/index.html +18 -0
- package/dist/index.js +22 -0
- package/docs/assets/highlight.css +22 -22
- package/docs/assets/icons.js +17 -17
- package/docs/assets/main.js +60 -60
- package/docs/assets/style.css +1640 -1640
- package/docs/classes/DBC.DBC.html +98 -98
- package/docs/classes/DBC_AE.AE.html +160 -160
- package/docs/classes/DBC_EQ.EQ.html +131 -131
- package/docs/classes/DBC_GREATER.GREATER.html +139 -139
- package/docs/classes/DBC_INSTANCE.INSTANCE.html +130 -130
- package/docs/classes/DBC_JSON.OP.JSON_OP.html +138 -138
- package/docs/classes/DBC_JSON.Parse.JSON_Parse.html +129 -129
- package/docs/classes/DBC_OR.OR.html +137 -137
- package/docs/classes/DBC_REGEX.REGEX.html +136 -136
- package/docs/classes/DBC_TYPE.TYPE.html +130 -130
- package/docs/classes/Demo.Demo.html +14 -14
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +1 -1
- package/docs/modules/DBC.html +1 -1
- package/docs/modules/DBC_AE.html +1 -1
- package/docs/modules/DBC_EQ.html +1 -1
- package/docs/modules/DBC_GREATER.html +1 -1
- package/docs/modules/DBC_INSTANCE.html +1 -1
- package/docs/modules/DBC_JSON.OP.html +1 -1
- package/docs/modules/DBC_JSON.Parse.html +1 -1
- package/docs/modules/DBC_OR.html +1 -1
- package/docs/modules/DBC_REGEX.html +1 -1
- package/docs/modules/DBC_TYPE.html +1 -1
- package/docs/modules/Demo.html +1 -1
- package/jest.config.js +32 -32
- package/package.json +71 -55
- package/src/DBC/AE.ts +269 -288
- package/src/DBC/ARR/PLAIN_OBJECT.ts +122 -133
- package/src/DBC/ARRAY.ts +117 -127
- package/src/DBC/COMPARISON/GREATER.ts +41 -46
- package/src/DBC/COMPARISON/GREATER_OR_EQUAL.ts +41 -45
- package/src/DBC/COMPARISON/LESS.ts +41 -45
- package/src/DBC/COMPARISON/LESS_OR_EQUAL.ts +41 -45
- package/src/DBC/COMPARISON.ts +149 -159
- package/src/DBC/DEFINED.ts +117 -122
- package/src/DBC/DOM.ts +453 -0
- package/src/DBC/EQ/DIFFERENT.ts +51 -57
- package/src/DBC/EQ.ts +154 -163
- package/src/DBC/HasAttribute.ts +149 -154
- package/src/DBC/IF.ts +173 -179
- package/src/DBC/INSTANCE.ts +168 -171
- package/src/DBC/JSON.OP.ts +178 -186
- package/src/DBC/JSON.Parse.ts +150 -157
- package/src/DBC/OR.ts +183 -187
- package/src/DBC/REGEX.ts +195 -196
- package/src/DBC/TYPE.ts +142 -149
- package/src/DBC/UNDEFINED.ts +115 -117
- package/src/DBC/ZOD.ts +130 -135
- package/src/DBC.ts +902 -904
- package/src/Demo.ts +537 -404
- package/src/index.ts +22 -0
- package/tsconfig.json +18 -18
- package/tsconfig.test.json +7 -7
- package/typedoc.json +16 -16
- package/webpack.config.js +27 -27
- package/Assessment.md +0 -507
package/README.md
CHANGED
|
@@ -1,408 +1,538 @@
|
|
|
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-
|
|
7
|
-
<img src="https://img.shields.io/badge/optimized%20for-VS%20Code-007acc?style=flat-square&logo=visualstudiocode" alt="VS Code" />
|
|
8
|
-
</p>
|
|
9
|
-
|
|
10
|
-
# XDBC — e**X**plicit **D**esign **b**y **C**ontract for TypeScript
|
|
11
|
-
|
|
12
|
-
> A decorator-based Design by Contract framework that enforces preconditions, postconditions, and invariants through TypeScript metadata — delivering precise, self-documenting, and verifiable component contracts.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## At a Glance
|
|
17
|
-
|
|
18
|
-
| Approach | With XDBC | Without XDBC |
|
|
19
|
-
|---|---|---|
|
|
20
|
-
| **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> |
|
|
21
|
-
| **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> |
|
|
22
|
-
| **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
|
-
|
|
24
|
-
Contract violations produce structured, actionable diagnostics:
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
[ XDBC Infringement [ From "method" in "MyClass": [ Parameter-value "+1d,+5d,-x10y"
|
|
28
|
-
of the 1st parameter did not fulfill one of it's contracts: Violating-Arrayelement at
|
|
29
|
-
index 2. Value has to comply to regular expression "/^(?i:(NOW)|([+-]\d+[dmy]))$/i"]]]
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Table of Contents
|
|
35
|
-
|
|
36
|
-
- [What is Design by Contract?](#what-is-design-by-contract)
|
|
37
|
-
- [Why XDBC?](#why-xdbc)
|
|
38
|
-
- [Installation](#installation)
|
|
39
|
-
- [
|
|
40
|
-
- [
|
|
41
|
-
- [
|
|
42
|
-
- [
|
|
43
|
-
- [
|
|
44
|
-
- [
|
|
45
|
-
- [
|
|
46
|
-
- [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
|
66
|
-
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
- **
|
|
79
|
-
- **
|
|
80
|
-
- **
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
|
159
|
-
|
|
160
|
-
| **`
|
|
161
|
-
| **`
|
|
162
|
-
| **`
|
|
163
|
-
| **`
|
|
164
|
-
| **`
|
|
165
|
-
| **`
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
|
176
|
-
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
|
195
|
-
|
|
196
|
-
| `
|
|
197
|
-
| `
|
|
198
|
-
| `
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
@
|
|
223
|
-
public
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
@
|
|
271
|
-
public
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
@
|
|
298
|
-
public
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
###
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
```typescript
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
);
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
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-experimentalDecorators-blue?style=flat-square" alt="decorators" />
|
|
7
|
+
<img src="https://img.shields.io/badge/optimized%20for-VS%20Code-007acc?style=flat-square&logo=visualstudiocode" alt="VS Code" />
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
# XDBC — e**X**plicit **D**esign **b**y **C**ontract for TypeScript
|
|
11
|
+
|
|
12
|
+
> A decorator-based Design by Contract framework that enforces preconditions, postconditions, and invariants through TypeScript metadata — delivering precise, self-documenting, and verifiable component contracts.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## At a Glance
|
|
17
|
+
|
|
18
|
+
| Approach | With XDBC | Without XDBC |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| **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> |
|
|
21
|
+
| **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> |
|
|
22
|
+
| **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
|
+
|
|
24
|
+
Contract violations produce structured, actionable diagnostics:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
[ XDBC Infringement [ From "method" in "MyClass": [ Parameter-value "+1d,+5d,-x10y"
|
|
28
|
+
of the 1st parameter did not fulfill one of it's contracts: Violating-Arrayelement at
|
|
29
|
+
index 2. Value has to comply to regular expression "/^(?i:(NOW)|([+-]\d+[dmy]))$/i"]]]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Table of Contents
|
|
35
|
+
|
|
36
|
+
- [What is Design by Contract?](#what-is-design-by-contract)
|
|
37
|
+
- [Why XDBC?](#why-xdbc)
|
|
38
|
+
- [Installation](#installation)
|
|
39
|
+
- [Decorator API](#decorator-api)
|
|
40
|
+
- [Quick Start](#quick-start)
|
|
41
|
+
- [Contracts Reference](#contracts-reference)
|
|
42
|
+
- [Core Concepts](#core-concepts)
|
|
43
|
+
- [Advanced Features](#advanced-features)
|
|
44
|
+
- [DOM / HTML Input Binding](#dom--html-input-binding)
|
|
45
|
+
- [Configuration](#configuration)
|
|
46
|
+
- [API Documentation](#api-documentation)
|
|
47
|
+
- [Built With XDBC](#built-with-xdbc)
|
|
48
|
+
- [Contributing](#contributing)
|
|
49
|
+
- [License](#license)
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## What is Design by Contract?
|
|
54
|
+
|
|
55
|
+
[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:
|
|
56
|
+
|
|
57
|
+
| Element | Purpose |
|
|
58
|
+
|---|---|
|
|
59
|
+
| **Preconditions** | Conditions that must hold true *before* a method executes |
|
|
60
|
+
| **Postconditions** | Guarantees that must hold true *after* a method returns |
|
|
61
|
+
| **Invariants** | Properties that must remain true *throughout* an object's lifetime |
|
|
62
|
+
|
|
63
|
+
### DbC vs. Assertions
|
|
64
|
+
|
|
65
|
+
| Aspect | XDBC Decorators | Manual Assertions |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| Formality | Formal, declarative, co-located with signatures | Informal, scattered through method bodies |
|
|
68
|
+
| Integration | TypeScript metadata and decorators | Built-in `console.assert` / `throw` |
|
|
69
|
+
| Expressiveness | Composable, parameterized contract objects | Simple boolean checks |
|
|
70
|
+
| Readability | Contracts are visible at the API surface | Validation logic obscures business logic |
|
|
71
|
+
| Maintainability | Contracts are localized and reusable | Duplicated checks are hard to track |
|
|
72
|
+
| Production control | Selectively enable/disable by contract type | Typically all-or-nothing |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Why XDBC?
|
|
77
|
+
|
|
78
|
+
- **Declarative** — contracts live as decorators alongside type signatures, not buried in method bodies
|
|
79
|
+
- **Composable** — combine contracts with `AE`, `OR`, and `IF` for expressive validation
|
|
80
|
+
- **Configurable** — toggle preconditions, postconditions, and invariants independently
|
|
81
|
+
- **Diagnostic** — structured error messages pinpoint the exact violation, parameter, and context
|
|
82
|
+
- **Extensible** — 16 built-in contracts, with support for custom contracts and Zod schema integration
|
|
83
|
+
- **Zero runtime overhead** — disable contract checking in production with a single flag
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Installation
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
npm install xdbc
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Requirements:** TypeScript 5.x with `experimentalDecorators` and `emitDecoratorMetadata` enabled in `tsconfig.json`.
|
|
94
|
+
|
|
95
|
+
```jsonc
|
|
96
|
+
// tsconfig.json
|
|
97
|
+
{
|
|
98
|
+
"compilerOptions": {
|
|
99
|
+
"experimentalDecorators": true,
|
|
100
|
+
"emitDecoratorMetadata": true
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Decorator API
|
|
108
|
+
|
|
109
|
+
XDBC is built on TypeScript's **legacy (`experimentalDecorators`) decorator API** — not the TC39 Stage 3 decorator API.
|
|
110
|
+
|
|
111
|
+
**Why?** Stage 3 decorators deliberately excluded parameter decorators from their scope. Parameter decorators are the foundation of XDBC's contract syntax: `@DEFINED.PRE()`, `@GREATER.PRE(0)`, and every other `PRE` contract applied per-parameter depends on them. There is no equivalent in Stage 3, and no workaround that preserves the same ergonomics.
|
|
112
|
+
|
|
113
|
+
**Is this unusual?** No. Some of the most widely adopted TypeScript frameworks in the industry require `experimentalDecorators` for exactly the same reason and have no near-term plans to migrate: on the backend, NestJS (used at thousands of companies, tens of millions of weekly downloads), TypeORM, class-validator, and class-transformer; on the frontend, `vue-class-component` (Vue's official class-based API) and MobX (the dominant React state management library for class-based stores). `experimentalDecorators: true` is compatible with Angular, Vue, and React — it is a TypeScript compiler flag, not a framework-level constraint, and does not conflict with any framework's runtime behavior. Any project already using these libraries has `experimentalDecorators: true` in its tsconfig and can adopt XDBC with zero additional configuration. For projects that don't, enabling it requires adding two lines to `tsconfig.json` — see [Installation](#installation).
|
|
114
|
+
|
|
115
|
+
**Is it risky?** No. TypeScript explicitly supports both APIs simultaneously and has made no announcement about removing `experimentalDecorators`. Any project already using the frameworks above already has `experimentalDecorators: true` in its tsconfig, meaning XDBC requires zero additional configuration in those environments.
|
|
116
|
+
|
|
117
|
+
**What about the future?** TC39 has an active Stage 1 proposal — [Class Method Parameter Decorators](https://github.com/tc39/proposals/blob/main/stage-1-proposals.md) (Ron Buckton, 2023) — that would close this gap. When parameter decorators reach a stable stage, XDBC will migrate to Stage 3. Because all decorator wiring is contained in `DBC.ts` and the 17 contract classes are completely insulated from it, that migration will be localized and non-breaking at the API level.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Quick Start
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { DBC, REGEX, TYPE, EQ } from "xdbc";
|
|
125
|
+
|
|
126
|
+
class UserService {
|
|
127
|
+
|
|
128
|
+
// Invariant: email must always match pattern
|
|
129
|
+
@REGEX.INVARIANT(/^[^@]+@[^@]+\.[^@]+$/)
|
|
130
|
+
public email = "user@example.com";
|
|
131
|
+
|
|
132
|
+
// Precondition: name must be a string; Postcondition: return must match pattern
|
|
133
|
+
@REGEX.POST(/^Hello, .+$/)
|
|
134
|
+
@DBC.ParamvalueProvider
|
|
135
|
+
public greet(@TYPE.PRE("string") name: string): string {
|
|
136
|
+
return `Hello, ${name}`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Precondition: age must be >= 0
|
|
140
|
+
@DBC.ParamvalueProvider
|
|
141
|
+
public setAge(@GREATER_OR_EQUAL.PRE(0) age: number) {
|
|
142
|
+
// ...
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Contracts Reference
|
|
150
|
+
|
|
151
|
+
XDBC ships with **16 contracts** organized into core validators and derived specializations:
|
|
152
|
+
|
|
153
|
+
### Core Contracts
|
|
154
|
+
|
|
155
|
+
| Contract | Description | Constructor |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| **`REGEX`** | Value must match a regular expression | `new REGEX(expression: RegExp)` |
|
|
158
|
+
| **`TYPE`** | Value must be of a specified type (supports pipe-separated: `"string\|number"`) | `new TYPE(type: string)` |
|
|
159
|
+
| **`EQ`** | Value must equal (or not equal) a reference value | `new EQ(equivalent: any, invert?: boolean)` |
|
|
160
|
+
| **`COMPARISON`** | Numeric comparison against a reference value | `new COMPARISON(equivalent, equalityPermitted, invert)` |
|
|
161
|
+
| **`INSTANCE`** | Value must be an instance of a specified class | `new INSTANCE(reference: any \| any[])` |
|
|
162
|
+
| **`AE`** | Every element in an array must satisfy a set of contracts | `new AE(conditions, index?, idxEnd?)` |
|
|
163
|
+
| **`OR`** | At least one of a set of contracts must be satisfied | `new OR(conditions: DBC[])` |
|
|
164
|
+
| **`IF`** | Conditional contract: if A holds, then B must also hold | `IF.PRE(condition, inCase, path?, invert?)` |
|
|
165
|
+
| **`JSON_OP`** | Object must contain specific properties of specific types | `new JSON_OP(properties: {name, type}[], checkElements?)` |
|
|
166
|
+
| **`JSON_Parse`** | String must be valid JSON; optionally forwards parsed result | `new JSON_Parse(receptor?: (json) => void)` |
|
|
167
|
+
| **`DEFINED`** | Value must not be `null` or `undefined` | — |
|
|
168
|
+
| **`UNDEFINED`** | Value must be `undefined` | — |
|
|
169
|
+
| **`ARRAY`** | Value must be an array | — |
|
|
170
|
+
| **`HasAttribute`** | HTMLElement must possess a named attribute | `HasAttribute.PRE(attrName, invert?)` |
|
|
171
|
+
| **`ZOD`** | Value must validate against a Zod schema | `new ZOD(schema: z.ZodType)` |
|
|
172
|
+
|
|
173
|
+
### Derived Contracts
|
|
174
|
+
|
|
175
|
+
| Contract | Derives From | Semantics |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| **`GREATER`** | `COMPARISON` | `value > reference` |
|
|
178
|
+
| **`GREATER_OR_EQUAL`** | `COMPARISON` | `value >= reference` |
|
|
179
|
+
| **`LESS`** | `COMPARISON` | `value < reference` |
|
|
180
|
+
| **`LESS_OR_EQUAL`** | `COMPARISON` | `value <= reference` |
|
|
181
|
+
| **`DIFFERENT`** | `EQ` | `value !== reference` |
|
|
182
|
+
| **`PLAIN_OBJECT`** | `ARRAY` | Value must be a non-null, non-array object |
|
|
183
|
+
|
|
184
|
+
### Built-in Regular Expressions
|
|
185
|
+
|
|
186
|
+
`REGEX.stdExp` provides ready-to-use patterns:
|
|
187
|
+
|
|
188
|
+
| Key | Validates |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `htmlAttributeName` | HTML attribute names |
|
|
191
|
+
| `eMail` | Email addresses |
|
|
192
|
+
| `property` | Property identifiers |
|
|
193
|
+
| `url` | URLs |
|
|
194
|
+
| `keyPath` | Key paths |
|
|
195
|
+
| `date` | Date strings |
|
|
196
|
+
| `dateFormat` | Date format patterns |
|
|
197
|
+
| `cssSelector` | CSS selectors |
|
|
198
|
+
| `boolean` | Boolean string literals |
|
|
199
|
+
| `colorCodeHEX` | Hex color codes |
|
|
200
|
+
| `simpleHotkey` | Keyboard shortcuts |
|
|
201
|
+
| `bcp47` | BCP 47 language tags |
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Core Concepts
|
|
206
|
+
|
|
207
|
+
### Decorator Types
|
|
208
|
+
|
|
209
|
+
Every contract exposes three decorator factories:
|
|
210
|
+
|
|
211
|
+
| Decorator | Applies To | Validates |
|
|
212
|
+
|---|---|---|
|
|
213
|
+
| `Contract.PRE(...)` | Method parameters | Input values before method execution |
|
|
214
|
+
| `Contract.POST(...)` | Methods | Return value after method execution |
|
|
215
|
+
| `Contract.INVARIANT(...)` | Fields / Properties | Value on every assignment (including initialization) |
|
|
216
|
+
|
|
217
|
+
### The `ParamvalueProvider` Decorator
|
|
218
|
+
|
|
219
|
+
TypeScript parameter decorators do not natively receive parameter values. Any method using `PRE` parameter contracts **must** be decorated with `@DBC.ParamvalueProvider`:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
@DBC.ParamvalueProvider
|
|
223
|
+
public process(
|
|
224
|
+
@TYPE.PRE("string") name: string,
|
|
225
|
+
@REGEX.PRE(/^\d{4}$/) code: string
|
|
226
|
+
) { ... }
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Path Resolution
|
|
230
|
+
|
|
231
|
+
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:
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
// Validate that element.tagName === "SELECT"
|
|
235
|
+
@DBC.ParamvalueProvider
|
|
236
|
+
public handleElement(@EQ.PRE("SELECT", false, "tagName") el: HTMLElement) { }
|
|
237
|
+
|
|
238
|
+
// Validate that value.length === 1
|
|
239
|
+
@EQ.INVARIANT(1, false, "length")
|
|
240
|
+
public singleChar = "X";
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Path resolution supports:
|
|
244
|
+
- **Dot notation**: `"user.address.city"`
|
|
245
|
+
- **Array indices**: `"items[0]"`
|
|
246
|
+
- **Method calls**: `"getName()"`
|
|
247
|
+
- **HTML attributes**: `"@data-id"`
|
|
248
|
+
|
|
249
|
+
### Custom Hints
|
|
250
|
+
|
|
251
|
+
Add context to error messages with the optional **`hint`** parameter:
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
@DBC.ParamvalueProvider
|
|
255
|
+
public setAge(
|
|
256
|
+
@GREATER_OR_EQUAL.PRE(0, undefined, "Age must be non-negative") age: number
|
|
257
|
+
) { }
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Advanced Features
|
|
263
|
+
|
|
264
|
+
### Composing Contracts with `AE`
|
|
265
|
+
|
|
266
|
+
Validate array elements against one or more contracts, optionally targeting a specific index range:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// All elements must be non-empty strings matching a date pattern
|
|
270
|
+
@AE.PRE([new TYPE("string"), new REGEX(/^\d{4}-\d{2}-\d{2}$/)])
|
|
271
|
+
public processDates(dates: string[]) { }
|
|
272
|
+
|
|
273
|
+
// Only elements at indices 1 through 3
|
|
274
|
+
@AE.PRE([new REGEX(/^[A-Z]+$/)], 1, 3)
|
|
275
|
+
public processRange(items: string[]) { }
|
|
276
|
+
|
|
277
|
+
// Single element at index 0
|
|
278
|
+
@AE.PRE([new TYPE("number")], 0)
|
|
279
|
+
public processFirst(values: unknown[]) { }
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Logical Composition with `OR`
|
|
283
|
+
|
|
284
|
+
At least one contract must pass:
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
@DBC.ParamvalueProvider
|
|
288
|
+
public setStatus(@OR.PRE([new EQ("active"), new EQ("inactive"), new EQ("pending")]) status: string) { }
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Conditional Contracts with `IF`
|
|
292
|
+
|
|
293
|
+
Apply a contract only when a precondition holds:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
// If the value is a string, it must also match digits-only
|
|
297
|
+
@IF.PRE(new TYPE("string"), new REGEX(/^\d+$/))
|
|
298
|
+
public processInput(value: unknown) { }
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Zod Schema Integration
|
|
302
|
+
|
|
303
|
+
Leverage Zod schemas for complex structural validation:
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
import { z } from "zod";
|
|
307
|
+
|
|
308
|
+
const UserSchema = z.object({
|
|
309
|
+
name: z.string().min(1),
|
|
310
|
+
email: z.string().email(),
|
|
311
|
+
age: z.number().int().positive()
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
@DBC.ParamvalueProvider
|
|
315
|
+
public createUser( @ZOD.PRE(UserSchema) data: unknown) { }
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Type-Safe Static Checks
|
|
319
|
+
|
|
320
|
+
Several contracts offer static `tsCheck` methods for imperative validation outside of decorators:
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
// Throws if value is not a string
|
|
324
|
+
const name = TYPE.tsCheck<string>(input, "string", "Expected a string");
|
|
325
|
+
|
|
326
|
+
// Throws if value doesn't match regex
|
|
327
|
+
const code = REGEX.tsCheck<string>(input, /^\d{4}$/, "Invalid code format");
|
|
328
|
+
|
|
329
|
+
// Throws if not an instance of Date
|
|
330
|
+
const date = INSTANCE.tsCheck<Date>(input, Date, "Expected a Date");
|
|
331
|
+
|
|
332
|
+
// Throws if none of the conditions pass
|
|
333
|
+
const result = OR.tsCheck<string>(input, [new EQ("a"), new EQ("b")]);
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## DOM / HTML Input Binding
|
|
339
|
+
|
|
340
|
+
XDBC can enforce contracts directly on `<input>` and `<textarea>` elements using HTML data attributes — no JavaScript wiring required per element.
|
|
341
|
+
|
|
342
|
+
### Setup
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
import { scanDOM } from "xdbc/DBC/DOM";
|
|
346
|
+
|
|
347
|
+
// Call once after the DOM is ready. Returns a cleanup function.
|
|
348
|
+
const cleanup = scanDOM();
|
|
349
|
+
|
|
350
|
+
// Optionally scope to a subtree:
|
|
351
|
+
const cleanup = scanDOM(document.getElementById("my-form"));
|
|
352
|
+
|
|
353
|
+
// Remove all listeners (e.g. on component unmount):
|
|
354
|
+
cleanup();
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Marking an element
|
|
358
|
+
|
|
359
|
+
Add `data-xdbc` to opt an element in. The optional value sets the DBC instance path (default: `"WaXCode.DBC"`):
|
|
360
|
+
|
|
361
|
+
```html
|
|
362
|
+
<input data-xdbc />
|
|
363
|
+
<input data-xdbc="MyApp.DBC" />
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Built-in contract attributes
|
|
367
|
+
|
|
368
|
+
| Attribute | Example value | Contract |
|
|
369
|
+
|---|---|---|
|
|
370
|
+
| `data-xdbc-regex` | `^\d*$` | `REGEX` |
|
|
371
|
+
| `data-xdbc-type` | `string\|number` | `TYPE` |
|
|
372
|
+
| `data-xdbc-eq` | `hello` | `EQ` |
|
|
373
|
+
| `data-xdbc-different` | `forbidden` | `EQ` (inverted) |
|
|
374
|
+
| `data-xdbc-defined` | *(no value needed)* | `DEFINED` |
|
|
375
|
+
| `data-xdbc-undefined` | *(no value needed)* | `UNDEFINED` |
|
|
376
|
+
| `data-xdbc-greater` | `5` | `COMPARISON` |
|
|
377
|
+
| `data-xdbc-greater-or-equal` | `5` | `COMPARISON` |
|
|
378
|
+
| `data-xdbc-less` | `100` | `COMPARISON` |
|
|
379
|
+
| `data-xdbc-less-or-equal` | `100` | `COMPARISON` |
|
|
380
|
+
| `data-xdbc-or` | `regex:^\d+$;;eq:N/A` | OR combinator (see below) |
|
|
381
|
+
|
|
382
|
+
Multiple attributes on one element are all enforced — the first failure blocks and reports.
|
|
383
|
+
|
|
384
|
+
### OR fragment syntax
|
|
385
|
+
|
|
386
|
+
Use `data-xdbc-or` to express that the value must satisfy **at least one** of several contracts. Fragments are separated by `;;`; each fragment is `<contract-key>:<value>`, where the split is on the **first** `:` only (so colons inside regex patterns are safe):
|
|
387
|
+
|
|
388
|
+
```html
|
|
389
|
+
<!-- digits, OR exactly the string "N/A" -->
|
|
390
|
+
<input data-xdbc data-xdbc-or="regex:^\d+$;;eq:N/A" />
|
|
391
|
+
|
|
392
|
+
<!-- http or https URL, OR the literal "N/A" -->
|
|
393
|
+
<input data-xdbc data-xdbc-or="regex:^https?://;;eq:N/A" />
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Behaviour on infringement
|
|
397
|
+
|
|
398
|
+
1. The element's value is **reverted** to the last accepted state, blocking the invalid input.
|
|
399
|
+
2. The DBC instance's `onInfringement`, `logToConsole`, and `throwException` settings are all honoured. Any throw is swallowed inside the event handler so it cannot propagate unhandled.
|
|
400
|
+
|
|
401
|
+
### IME / composition awareness
|
|
402
|
+
|
|
403
|
+
Validation is suspended during IME composition (e.g. CJK on-screen keyboards) and runs once on `compositionend`, so partially composed characters are never incorrectly rejected.
|
|
404
|
+
|
|
405
|
+
### Registering custom contracts
|
|
406
|
+
|
|
407
|
+
Use `registerDOMContract` to add any contract — including future ones — without modifying the library:
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
import { registerDOMContract } from "xdbc/DBC/DOM";
|
|
411
|
+
import { MY_CONTRACT } from "./MY_CONTRACT";
|
|
412
|
+
|
|
413
|
+
// Register once, before scanDOM():
|
|
414
|
+
registerDOMContract("my-contract", (value, attrValue) =>
|
|
415
|
+
MY_CONTRACT.checkAlgorithm(value, attrValue),
|
|
416
|
+
);
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
```html
|
|
420
|
+
<input data-xdbc data-xdbc-my-contract="someConfig" />
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
The `attrValue` string is whatever appears in the attribute — parse it however your contract needs.
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Configuration
|
|
428
|
+
|
|
429
|
+
### DBC Instance Settings
|
|
430
|
+
|
|
431
|
+
A default DBC instance is automatically registered at `WaXCode.DBC` when the module is imported. You can access and configure it:
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
import { DBC } from "xdbc";
|
|
435
|
+
|
|
436
|
+
// Access the default DBC instance
|
|
437
|
+
const dbc = (globalThis as any).WaXCode.DBC as DBC;
|
|
438
|
+
|
|
439
|
+
// Toggle contract checking
|
|
440
|
+
dbc.executionSettings.checkPreconditions = true;
|
|
441
|
+
dbc.executionSettings.checkPostconditions = true;
|
|
442
|
+
dbc.executionSettings.checkInvariants = true;
|
|
443
|
+
|
|
444
|
+
// Configure infringement handling
|
|
445
|
+
dbc.infringementSettings.throwException = true; // throw DBC.Infringement on violation
|
|
446
|
+
dbc.infringementSettings.logToConsole = false; // log to console instead
|
|
447
|
+
|
|
448
|
+
# React to infringements programmatically
|
|
449
|
+
dbc.infringementSettings.onInfringement = (infringement, context) => {
|
|
450
|
+
// infringement — DBC.Infringement instance (extends Error, has .message and .stack)
|
|
451
|
+
// context.type — "precondition" | "postcondition" | "invariant"
|
|
452
|
+
// context.value — the raw value that violated the contract
|
|
453
|
+
Sentry.captureException(infringement, { extra: context });
|
|
454
|
+
};
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
The callback fires **before** `throwException`, so it always runs even when an exception is thrown. All three settings are independent and can be combined freely.
|
|
458
|
+
|
|
459
|
+
### Multiple DBC Instances
|
|
460
|
+
|
|
461
|
+
Create isolated DBC instances with separate configurations using `DBC.register()`:
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
// Register a vendor-specific instance at a custom path
|
|
465
|
+
const vendorDbc = new DBC(
|
|
466
|
+
{ throwException: false, logToConsole: true },
|
|
467
|
+
);
|
|
468
|
+
DBC.register(vendorDbc, "MyVendor.DBC");
|
|
469
|
+
|
|
470
|
+
// Route a contract to the custom instance via its path
|
|
471
|
+
@REGEX.INVARIANT(/^[A-Z]+$/, undefined, undefined, "MyVendor.DBC")
|
|
472
|
+
public code = "ABC";
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
> **Note:** `new DBC()` does not automatically mount onto `globalThis`. Call `DBC.register(instance, path)` to make an instance available for decorator resolution.
|
|
476
|
+
|
|
477
|
+
### Test Isolation
|
|
478
|
+
|
|
479
|
+
Use `DBC.isolated()` to run tests with a temporary DBC instance that doesn't affect other tests:
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
DBC.isolated((tempDbc) => {
|
|
483
|
+
// tempDbc is registered at "WaXCode.DBC" for the duration of this callback
|
|
484
|
+
tempDbc.executionSettings.checkPreconditions = false;
|
|
485
|
+
|
|
486
|
+
// ... run tests with contracts disabled ...
|
|
487
|
+
});
|
|
488
|
+
// Original DBC instance is automatically restored here
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Disabling Contracts in Production
|
|
492
|
+
|
|
493
|
+
```typescript
|
|
494
|
+
const dbc = (globalThis as any).WaXCode.DBC as DBC;
|
|
495
|
+
dbc.executionSettings.checkPreconditions = false;
|
|
496
|
+
dbc.executionSettings.checkPostconditions = false;
|
|
497
|
+
dbc.executionSettings.checkInvariants = false;
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
## API Documentation
|
|
503
|
+
|
|
504
|
+
Full generated API documentation is available at **[callaris.github.io/XDBC](https://callaris.github.io/XDBC/)**.
|
|
505
|
+
|
|
506
|
+
See [`Demo.ts`](src/Demo.ts) for annotated usage examples.
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## Built With XDBC
|
|
511
|
+
|
|
512
|
+
XDBC is actively used in production across the following projects:
|
|
513
|
+
|
|
514
|
+
| Project | Context |
|
|
515
|
+
|---|---|
|
|
516
|
+
| [CodBi](https://github.com/XIMA-formcycle-Entwicklerkreis/CodBi) | Low-code engine plugin for [XIMA Formcycle](https://www.xima.de/formcycle) |
|
|
517
|
+
| [tinymce-multicloud-plugin](https://github.com/CallariS/tinymce-multicloud-plugin) | multiCloud plugin for [TinyMCE](https://www.tiny.cloud) |
|
|
518
|
+
| *(internal)* | Comprehensive Active Directory management suite for schools, deployed at a German public administration |
|
|
519
|
+
|
|
520
|
+
*XDBC is used in the Angular frontends of the above projects.*
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Contributing
|
|
525
|
+
|
|
526
|
+
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.
|
|
527
|
+
|
|
528
|
+
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines, and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for community standards.
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## License
|
|
533
|
+
|
|
534
|
+
[MIT](LICENSE) © Callari, Salvatore
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
<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>
|