xdbc 1.0.217 → 1.0.218

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 (89) hide show
  1. package/.gitattributes +8 -0
  2. package/.vscode/settings.json +3 -3
  3. package/.vscode/tasks.json +23 -23
  4. package/ASSESSMENT.md +249 -0
  5. package/README.md +131 -1
  6. package/__tests__/DBC/AE.test.ts +62 -62
  7. package/__tests__/DBC/ARRAY.test.ts +91 -91
  8. package/__tests__/DBC/DEFINED.test.ts +53 -53
  9. package/__tests__/DBC/DOM.test.ts +481 -0
  10. package/__tests__/DBC/Decorators.test.ts +367 -367
  11. package/__tests__/DBC/EQ.test.ts +13 -13
  12. package/__tests__/DBC/GREATER.test.ts +31 -31
  13. package/__tests__/DBC/HasAttribute.test.ts +60 -60
  14. package/__tests__/DBC/IF.test.ts +62 -62
  15. package/__tests__/DBC/INSTANCE.test.ts +13 -13
  16. package/__tests__/DBC/JSON.OP.test.ts +47 -47
  17. package/__tests__/DBC/JSON.Parse.test.ts +17 -17
  18. package/__tests__/DBC/OR.test.ts +14 -14
  19. package/__tests__/DBC/PLAIN_OBJECT.test.ts +109 -109
  20. package/__tests__/DBC/REGEX.test.ts +17 -17
  21. package/__tests__/DBC/TYPE.test.ts +13 -13
  22. package/__tests__/DBC/UNDEFINED.test.ts +45 -45
  23. package/__tests__/DBC/ZOD.test.ts +54 -54
  24. package/__tests__/DBC/onInfringement.test.ts +262 -0
  25. package/biome.json +40 -40
  26. package/dist/DBC/AE.js +172 -0
  27. package/dist/DBC/ARR/PLAIN_OBJECT.d.ts +0 -3
  28. package/dist/DBC/ARR/PLAIN_OBJECT.js +95 -0
  29. package/dist/DBC/ARRAY.d.ts +0 -3
  30. package/dist/DBC/ARRAY.js +90 -0
  31. package/dist/DBC/COMPARISON/GREATER.js +21 -0
  32. package/dist/DBC/COMPARISON/GREATER_OR_EQUAL.js +21 -0
  33. package/dist/DBC/COMPARISON/LESS.js +21 -0
  34. package/dist/DBC/COMPARISON/LESS_OR_EQUAL.js +21 -0
  35. package/dist/DBC/COMPARISON.js +98 -0
  36. package/dist/DBC/DEFINED.js +87 -0
  37. package/dist/DBC/DOM.d.ts +87 -0
  38. package/dist/DBC/DOM.js +223 -0
  39. package/dist/DBC/EQ/DIFFERENT.js +34 -0
  40. package/dist/DBC/EQ.js +101 -0
  41. package/dist/DBC/HasAttribute.js +101 -0
  42. package/dist/DBC/IF.js +96 -0
  43. package/dist/DBC/INSTANCE.js +122 -0
  44. package/dist/DBC/JSON.OP.js +120 -0
  45. package/dist/DBC/JSON.Parse.js +104 -0
  46. package/dist/DBC/OR.js +125 -0
  47. package/dist/DBC/REGEX.js +136 -0
  48. package/dist/DBC/TYPE.js +112 -0
  49. package/dist/DBC/UNDEFINED.js +87 -0
  50. package/dist/DBC/ZOD.js +99 -0
  51. package/dist/DBC.d.ts +18 -4
  52. package/dist/DBC.js +645 -0
  53. package/dist/Demo.d.ts +10 -0
  54. package/dist/Demo.js +713 -0
  55. package/dist/bundle.js +6140 -405
  56. package/dist/index.d.ts +22 -0
  57. package/dist/index.js +22 -0
  58. package/jest.config.js +32 -32
  59. package/package.json +71 -55
  60. package/src/DBC/AE.ts +269 -288
  61. package/src/DBC/ARR/PLAIN_OBJECT.ts +122 -133
  62. package/src/DBC/ARRAY.ts +117 -127
  63. package/src/DBC/COMPARISON/GREATER.ts +41 -46
  64. package/src/DBC/COMPARISON/GREATER_OR_EQUAL.ts +41 -45
  65. package/src/DBC/COMPARISON/LESS.ts +41 -45
  66. package/src/DBC/COMPARISON/LESS_OR_EQUAL.ts +41 -45
  67. package/src/DBC/COMPARISON.ts +149 -159
  68. package/src/DBC/DEFINED.ts +117 -122
  69. package/src/DBC/DOM.ts +291 -0
  70. package/src/DBC/EQ/DIFFERENT.ts +51 -57
  71. package/src/DBC/EQ.ts +154 -163
  72. package/src/DBC/HasAttribute.ts +149 -154
  73. package/src/DBC/IF.ts +173 -179
  74. package/src/DBC/INSTANCE.ts +168 -171
  75. package/src/DBC/JSON.OP.ts +178 -186
  76. package/src/DBC/JSON.Parse.ts +150 -157
  77. package/src/DBC/OR.ts +183 -187
  78. package/src/DBC/REGEX.ts +195 -196
  79. package/src/DBC/TYPE.ts +142 -149
  80. package/src/DBC/UNDEFINED.ts +115 -117
  81. package/src/DBC/ZOD.ts +130 -135
  82. package/src/DBC.ts +902 -904
  83. package/src/Demo.ts +537 -404
  84. package/src/index.ts +22 -0
  85. package/tsconfig.json +18 -18
  86. package/tsconfig.test.json +7 -7
  87. package/typedoc.json +16 -16
  88. package/webpack.config.js +27 -27
  89. package/Assessment.md +0 -507
@@ -0,0 +1,262 @@
1
+ import "reflect-metadata";
2
+ import { DBC } from "../../src/DBC";
3
+ import { TYPE } from "../../src/DBC/TYPE";
4
+
5
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
6
+
7
+ type InfringementCallback = (
8
+ infringement: InstanceType<typeof DBC.Infringement>,
9
+ context: {
10
+ type: "precondition" | "postcondition" | "invariant";
11
+ value: unknown;
12
+ },
13
+ ) => void;
14
+
15
+ function makeDbcWithSpy(throwException = false): {
16
+ dbc: DBC;
17
+ spy: jest.MockedFunction<InfringementCallback>;
18
+ } {
19
+ const spy = jest.fn<void, Parameters<InfringementCallback>>();
20
+ const dbc = new DBC({
21
+ throwException,
22
+ logToConsole: false,
23
+ onInfringement: spy,
24
+ });
25
+ return { dbc, spy };
26
+ }
27
+
28
+ // ─── reportParameterInfringement ─────────────────────────────────────────────
29
+
30
+ describe("onInfringement — reportParameterInfringement", () => {
31
+ test("calls callback with a DBC.Infringement instance", () => {
32
+ const { dbc, spy } = makeDbcWithSpy();
33
+ dbc.reportParameterInfringement(
34
+ "must be a string",
35
+ {},
36
+ undefined,
37
+ "myMethod",
38
+ 0,
39
+ 42,
40
+ );
41
+ expect(spy).toHaveBeenCalledTimes(1);
42
+ expect(spy.mock.calls[0][0]).toBeInstanceOf(DBC.Infringement);
43
+ });
44
+
45
+ test("context.type is 'precondition'", () => {
46
+ const { dbc, spy } = makeDbcWithSpy();
47
+ dbc.reportParameterInfringement(
48
+ "must be a string",
49
+ {},
50
+ undefined,
51
+ "myMethod",
52
+ 0,
53
+ 42,
54
+ );
55
+ expect(spy.mock.calls[0][1].type).toBe("precondition");
56
+ });
57
+
58
+ test("context.value reflects the violating argument", () => {
59
+ const { dbc, spy } = makeDbcWithSpy();
60
+ dbc.reportParameterInfringement(
61
+ "must be a string",
62
+ {},
63
+ undefined,
64
+ "myMethod",
65
+ 0,
66
+ 42,
67
+ );
68
+ expect(spy.mock.calls[0][1].value).toBe(42);
69
+ });
70
+
71
+ test("callback is invoked before the exception is thrown", () => {
72
+ const order: string[] = [];
73
+ const spy = jest.fn(() => order.push("callback"));
74
+ const dbc = new DBC({
75
+ throwException: true,
76
+ logToConsole: false,
77
+ onInfringement: spy,
78
+ });
79
+ try {
80
+ dbc.reportParameterInfringement("msg", {}, undefined, "m", 0, null);
81
+ } catch {
82
+ order.push("throw");
83
+ }
84
+ expect(order).toEqual(["callback", "throw"]);
85
+ });
86
+
87
+ test("thrown error is a DBC.Infringement", () => {
88
+ const { dbc } = makeDbcWithSpy(true);
89
+ expect(() =>
90
+ dbc.reportParameterInfringement("msg", {}, undefined, "m", 0, undefined),
91
+ ).toThrow(DBC.Infringement);
92
+ });
93
+
94
+ test("callback is not called when throwException is true and no infringement", () => {
95
+ const { spy } = makeDbcWithSpy(true);
96
+ // No call made — spy must stay silent
97
+ expect(spy).not.toHaveBeenCalled();
98
+ });
99
+ });
100
+
101
+ // ─── reportFieldInfringement ──────────────────────────────────────────────────
102
+
103
+ describe("onInfringement — reportFieldInfringement", () => {
104
+ test("calls callback with a DBC.Infringement instance", () => {
105
+ const { dbc, spy } = makeDbcWithSpy();
106
+ dbc.reportFieldInfringement("must be positive", {}, undefined, "count", -1);
107
+ expect(spy).toHaveBeenCalledTimes(1);
108
+ expect(spy.mock.calls[0][0]).toBeInstanceOf(DBC.Infringement);
109
+ });
110
+
111
+ test("context.type is 'invariant'", () => {
112
+ const { dbc, spy } = makeDbcWithSpy();
113
+ dbc.reportFieldInfringement("must be positive", {}, undefined, "count", -1);
114
+ expect(spy.mock.calls[0][1].type).toBe("invariant");
115
+ });
116
+
117
+ test("context.value reflects the violating field value", () => {
118
+ const { dbc, spy } = makeDbcWithSpy();
119
+ dbc.reportFieldInfringement("must be positive", {}, undefined, "count", -1);
120
+ expect(spy.mock.calls[0][1].value).toBe(-1);
121
+ });
122
+ });
123
+
124
+ // ─── reportReturnvalueInfringement ───────────────────────────────────────────
125
+
126
+ describe("onInfringement — reportReturnvalueInfringement", () => {
127
+ test("calls callback with a DBC.Infringement instance", () => {
128
+ const { dbc, spy } = makeDbcWithSpy();
129
+ dbc.reportReturnvalueInfringement(
130
+ "must not be null",
131
+ {},
132
+ undefined,
133
+ "getUser",
134
+ null,
135
+ );
136
+ expect(spy).toHaveBeenCalledTimes(1);
137
+ expect(spy.mock.calls[0][0]).toBeInstanceOf(DBC.Infringement);
138
+ });
139
+
140
+ test("context.type is 'postcondition'", () => {
141
+ const { dbc, spy } = makeDbcWithSpy();
142
+ dbc.reportReturnvalueInfringement(
143
+ "must not be null",
144
+ {},
145
+ undefined,
146
+ "getUser",
147
+ null,
148
+ );
149
+ expect(spy.mock.calls[0][1].type).toBe("postcondition");
150
+ });
151
+
152
+ test("context.value reflects the violating return value", () => {
153
+ const { dbc, spy } = makeDbcWithSpy();
154
+ dbc.reportReturnvalueInfringement(
155
+ "must not be null",
156
+ {},
157
+ undefined,
158
+ "getUser",
159
+ null,
160
+ );
161
+ expect(spy.mock.calls[0][1].value).toBeNull();
162
+ });
163
+ });
164
+
165
+ // ─── reportTsCheckInfringement ───────────────────────────────────────────────
166
+
167
+ describe("onInfringement — reportTsCheckInfringement", () => {
168
+ test("calls callback with a DBC.Infringement instance and precondition context", () => {
169
+ const spy = jest.fn<void, Parameters<InfringementCallback>>();
170
+ DBC.isolated((dbc) => {
171
+ dbc.infringementSettings.throwException = false;
172
+ dbc.infringementSettings.onInfringement = spy;
173
+ DBC.reportTsCheckInfringement("value must be > 0", undefined, -5);
174
+ });
175
+ expect(spy).toHaveBeenCalledTimes(1);
176
+ expect(spy.mock.calls[0][0]).toBeInstanceOf(DBC.Infringement);
177
+ expect(spy.mock.calls[0][1].type).toBe("precondition");
178
+ });
179
+
180
+ test("context.value is the value passed to reportTsCheckInfringement", () => {
181
+ const spy = jest.fn<void, Parameters<InfringementCallback>>();
182
+ DBC.isolated((dbc) => {
183
+ dbc.infringementSettings.throwException = false;
184
+ dbc.infringementSettings.onInfringement = spy;
185
+ DBC.reportTsCheckInfringement("msg", undefined, "badValue");
186
+ });
187
+ expect(spy.mock.calls[0][1].value).toBe("badValue");
188
+ });
189
+
190
+ test("throws DBC.Infringement even when no instance is registered", () => {
191
+ expect(() =>
192
+ DBC.reportTsCheckInfringement("msg", "XDBC.NonExistent.Path"),
193
+ ).toThrow(DBC.Infringement);
194
+ });
195
+
196
+ test("callback is called before exception is thrown", () => {
197
+ const order: string[] = [];
198
+ const spy = jest.fn(() => order.push("callback"));
199
+ DBC.isolated((dbc) => {
200
+ dbc.infringementSettings.throwException = true;
201
+ dbc.infringementSettings.onInfringement = spy;
202
+ try {
203
+ DBC.reportTsCheckInfringement("msg");
204
+ } catch {
205
+ order.push("throw");
206
+ }
207
+ });
208
+ expect(order).toEqual(["callback", "throw"]);
209
+ });
210
+ });
211
+
212
+ // ─── Decorator integration ────────────────────────────────────────────────────
213
+ //
214
+ // Each test calls makeTypedSubject() to create a fresh class whose decorator closures
215
+ // have an un-cached dbcInstance. That way DBC.isolated()'s registered instance is
216
+ // always picked up on the first (and only) call within that block.
217
+ //
218
+
219
+ function makeTypedSubject() {
220
+ class Subject {
221
+ @DBC.ParamvalueProvider
222
+ public typed(@TYPE.PRE("string") value: unknown): unknown {
223
+ return value;
224
+ }
225
+ }
226
+ return new Subject();
227
+ }
228
+
229
+ describe("onInfringement — decorator integration", () => {
230
+ test("onInfringement is called via @TYPE.PRE infringement (precondition)", () => {
231
+ const spy = jest.fn<void, Parameters<InfringementCallback>>();
232
+ DBC.isolated((dbc) => {
233
+ dbc.infringementSettings.throwException = false;
234
+ dbc.infringementSettings.onInfringement = spy;
235
+ makeTypedSubject().typed(99);
236
+ });
237
+ expect(spy).toHaveBeenCalledTimes(1);
238
+ expect(spy.mock.calls[0][0]).toBeInstanceOf(DBC.Infringement);
239
+ expect(spy.mock.calls[0][1].type).toBe("precondition");
240
+ expect(spy.mock.calls[0][1].value).toBe(99);
241
+ });
242
+
243
+ test("onInfringement is not called when contract is satisfied", () => {
244
+ const spy = jest.fn<void, Parameters<InfringementCallback>>();
245
+ DBC.isolated((dbc) => {
246
+ dbc.infringementSettings.throwException = false;
247
+ dbc.infringementSettings.onInfringement = spy;
248
+ makeTypedSubject().typed("valid");
249
+ });
250
+ expect(spy).not.toHaveBeenCalled();
251
+ });
252
+
253
+ test("the Infringement message contains the raw message text", () => {
254
+ const spy = jest.fn<void, Parameters<InfringementCallback>>();
255
+ DBC.isolated((dbc) => {
256
+ dbc.infringementSettings.throwException = false;
257
+ dbc.infringementSettings.onInfringement = spy;
258
+ makeTypedSubject().typed(true);
259
+ });
260
+ expect(spy.mock.calls[0][0].message).toContain("XDBC Infringement");
261
+ });
262
+ });
package/biome.json CHANGED
@@ -1,40 +1,40 @@
1
- {
2
- "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3
- "vcs": {
4
- "enabled": false,
5
- "clientKind": "git",
6
- "useIgnoreFile": false
7
- },
8
- "files": {
9
- "ignoreUnknown": false,
10
- "ignore": ["dist/**", "node_modules/**", "docs/**", "coverage/**"]
11
- },
12
- "formatter": {
13
- "enabled": true,
14
- "indentStyle": "tab"
15
- },
16
- "organizeImports": {
17
- "enabled": true
18
- },
19
- "linter": {
20
- "enabled": true,
21
- "rules": {
22
- "recommended": true,
23
- "suspicious": {
24
- "noExplicitAny": "off",
25
- "useValidTypeof": "off"
26
- },
27
- "style": {
28
- "noNonNullAssertion": "off"
29
- }
30
- }
31
- },
32
- "javascript": {
33
- "parser": {
34
- "unsafeParameterDecoratorsEnabled": true
35
- },
36
- "formatter": {
37
- "quoteStyle": "double"
38
- }
39
- }
40
- }
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3
+ "vcs": {
4
+ "enabled": false,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": false
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false,
10
+ "ignore": ["dist/**", "node_modules/**", "docs/**", "coverage/**"]
11
+ },
12
+ "formatter": {
13
+ "enabled": true,
14
+ "indentStyle": "tab"
15
+ },
16
+ "organizeImports": {
17
+ "enabled": true
18
+ },
19
+ "linter": {
20
+ "enabled": true,
21
+ "rules": {
22
+ "recommended": true,
23
+ "suspicious": {
24
+ "noExplicitAny": "off",
25
+ "useValidTypeof": "off"
26
+ },
27
+ "style": {
28
+ "noNonNullAssertion": "off"
29
+ }
30
+ }
31
+ },
32
+ "javascript": {
33
+ "parser": {
34
+ "unsafeParameterDecoratorsEnabled": true
35
+ },
36
+ "formatter": {
37
+ "quoteStyle": "double"
38
+ }
39
+ }
40
+ }
package/dist/DBC/AE.js ADDED
@@ -0,0 +1,172 @@
1
+ import { DBC } from "../DBC";
2
+ /**
3
+ * A {@link DBC } defining that all elements of an {@link object }s have to fulfill
4
+ * a given {@link object }'s check-method (**( toCheck : any ) => boolean | string**).
5
+ *
6
+ * @remarks
7
+ * Maintainer: Callari, Salvatore (XDBC@WaXCode.net) */
8
+ export class AE extends DBC {
9
+ // #region Condition checking.
10
+ /**
11
+ * Checks each element of the **value**-{@link Array < any >} against the given **condition**, if it is one. If it is not
12
+ * the **value** itself will be checked.
13
+ *
14
+ * @param condition The { check: (toCheck: any) => boolean | string } to check the **value** against.
15
+ * @param value Either **value**-{@link Array < any >}, which's elements will be checked, or the value to be
16
+ * checked itself.
17
+ * @param index If specified with **idxEnd** being undefined, this {@link Number } will be seen as the index of
18
+ * the value-{@link Array }'s element to check. If value isn't an {@link Array } this parameter
19
+ * will not have any effect.
20
+ * With **idxEnd** not undefined this parameter indicates the beginning of the span of elements to
21
+ * check within the value-{@link Array }.
22
+ * @param idxEnd Indicates the last element's index (including) of the span of value-{@link Array } elements to check.
23
+ * Setting this parameter to -1 specifies that all value-{@link Array }'s elements beginning from the
24
+ * specified **index** shall be checked.
25
+ *
26
+ * @returns As soon as the **condition** returns a {@link string }, instead of TRUE, the returned string. TRUE if the
27
+ * **condition** never returns a {@link string}. */
28
+ static checkAlgorithm(condition, value, index, idxEnd) {
29
+ if (Array.isArray(value)) {
30
+ if (index !== undefined && idxEnd === undefined) {
31
+ if (index > -1 && index < value.length) {
32
+ const result = condition.check(value[index]);
33
+ if (typeof result === "string") {
34
+ return `Violating-Arrayelement at index "${index}" with value "${value[index]}". ${result}`;
35
+ }
36
+ }
37
+ return true; // In order for optional parameter to not cause an error if they are omitted.
38
+ }
39
+ const ending = idxEnd !== undefined
40
+ ? idxEnd !== -1
41
+ ? idxEnd + 1
42
+ : value.length
43
+ : value.length;
44
+ for (let i = index ? index : 0; i < ending; i++) {
45
+ const result = condition.check(value[i]);
46
+ if (result !== true) {
47
+ return `Violating-Arrayelement at index ${i}. ${result}`;
48
+ }
49
+ }
50
+ }
51
+ else {
52
+ return condition.check(value);
53
+ }
54
+ return true;
55
+ }
56
+ /**
57
+ * A parameter-decorator factory using the {@link AE.checkAlgorithm } with either multiple or a single one
58
+ * of the **realConditions** to check the tagged parameter-value against with.
59
+ * When specifying an **index** and the tagged parameter's **value** is an {@link Array }, the **realConditions** apply to the
60
+ * element at the specified **index**.
61
+ * If the {@link Array } is too short the currently processed { check: (toCheck: any) => boolean | string } of
62
+ * **realConditions** will be verified to TRUE automatically, considering optional parameters.
63
+ * If an **index** is specified but the tagged parameter's value isn't an array, the **index** is treated as being undefined.
64
+ * If **index** is undefined and the tagged parameter's value is an {@link Array } each element of it will be checked
65
+ * against the **realConditions**.
66
+ *
67
+ * @param realConditions Either one or more { check: (toCheck: any) => boolean | string } to check the tagged parameter-value
68
+ * against with.
69
+ * @param index See the {@link AE.checkAlgorithm }.
70
+ * @param idxEnd See the {@link AE.checkAlgorithm }.
71
+ * @param path See {@link DBC.decPrecondition }.
72
+ * @param hint See {@link DBC.decPrecondition }.
73
+ * @param dbc See {@link DBC.decPrecondition }.
74
+ *
75
+ * @returns A {@link string } as soon as one { check: (toCheck: any) => boolean | string } of **realConditions** returns one.
76
+ * Otherwise TRUE. */
77
+ static PRE(realConditions, index = undefined, idxEnd = undefined, path = undefined, hint = undefined, dbc = undefined) {
78
+ return DBC.decPrecondition((value, target, methodName, parameterIndex) => {
79
+ if (Array.isArray(realConditions)) {
80
+ for (const currentCondition of realConditions) {
81
+ const result = AE.checkAlgorithm(currentCondition, value, index, idxEnd);
82
+ if (typeof result !== "boolean")
83
+ return result;
84
+ }
85
+ }
86
+ else {
87
+ return AE.checkAlgorithm(realConditions, value, index, idxEnd);
88
+ }
89
+ return true;
90
+ }, dbc, path, hint);
91
+ }
92
+ /**
93
+ * A method-decorator factory using the {@link AE.checkAlgorithm } with either multiple or a single one
94
+ * of the **realConditions** to check the tagged method's return-value against with.
95
+ *
96
+ * @param realConditions Either one or more { check: (toCheck: any) => boolean | string } to check the tagged parameter-value
97
+ * against with.
98
+ * @param index See the {@link AE.checkAlgorithm }.
99
+ * @param idxEnd See the {@link AE.checkAlgorithm }.
100
+ * @param path See {@link DBC.decPrecondition }.
101
+ * @param hint See {@link DBC.decPrecondition }.
102
+ * @param dbc See {@link DBC.decPrecondition }.
103
+ *
104
+ * @returns A {@link string } as soon as one { check: (toCheck: any) => boolean | string } of **realConditions** return one.
105
+ * Otherwise TRUE. */
106
+ static POST(realConditions, index = undefined, idxEnd = undefined, path = undefined, hint = undefined, dbc = undefined) {
107
+ return DBC.decPostcondition((value, target, propertyKey) => {
108
+ if (Array.isArray(realConditions)) {
109
+ for (const currentCondition of realConditions) {
110
+ const result = AE.checkAlgorithm(currentCondition, value, index, idxEnd);
111
+ if (typeof result !== "boolean")
112
+ return result;
113
+ }
114
+ }
115
+ else {
116
+ return AE.checkAlgorithm(realConditions, value, index, idxEnd);
117
+ }
118
+ return true;
119
+ }, dbc, path, hint);
120
+ }
121
+ /**
122
+ * A field-decorator factory using the {@link AE.checkAlgorithm } with either multiple or a single one
123
+ * of the **realConditions** to check the tagged field.
124
+ *
125
+ * @param realConditions Either one or more { check: (toCheck: any) => boolean | string } to check the tagged parameter-value
126
+ * against with.
127
+ * @param index See the {@link AE.checkAlgorithm }.
128
+ * @param idxEnd See the {@link AE.checkAlgorithm }.
129
+ * @param path See {@link DBC.decInvariant }.
130
+ * @param hint See {@link DBC.decInvariant }.
131
+ * @param dbc See {@link DBC.decInvariant }.
132
+ *
133
+ * @returns See {@link DBC.decInvariant }. */
134
+ static INVARIANT(realConditions, index = undefined, idxEnd = undefined, path = undefined, hint = undefined, dbc = undefined) {
135
+ return DBC.createINVARIANT(AE, [realConditions, index, idxEnd], dbc, path, hint);
136
+ }
137
+ // #endregion Condition checking.
138
+ // #region Referenced Condition checking.
139
+ //
140
+ // For usage in dynamic scenarios (like global functions).
141
+ //
142
+ /**
143
+ * Invokes the {@link AE.checkAlgorithm } with all {@link AE.conditions } and the {@link object } {@link toCheck },
144
+ * {@link AE.index } & {@link AE.idxEnd }.
145
+ *
146
+ * @param toCheck See {@link AE.checkAlgorithm }.
147
+ *
148
+ * @returns See {@link EQ.checkAlgorithm}. */
149
+ check(toCheck) {
150
+ if (Array.isArray(this.conditions)) {
151
+ for (const currentCondition of this.conditions) {
152
+ const result = AE.checkAlgorithm(currentCondition, toCheck, this.index, this.idxEnd);
153
+ if (typeof result !== "boolean")
154
+ return result;
155
+ }
156
+ }
157
+ else {
158
+ return AE.checkAlgorithm(this.conditions, toCheck, this.index, this.idxEnd);
159
+ }
160
+ return true;
161
+ }
162
+ /**
163
+ * Creates this {@link AE } by setting the protected property {@link AE.conditions }, {@link AE.index } and {@link AE.idxEnd } used by {@link AE.check }.
164
+ *
165
+ * @param equivalent See {@link EQ.check }. */
166
+ constructor(conditions, index = undefined, idxEnd = undefined) {
167
+ super();
168
+ this.conditions = conditions;
169
+ this.index = index;
170
+ this.idxEnd = idxEnd;
171
+ }
172
+ }
@@ -61,7 +61,4 @@ export declare class PLAIN_OBJECT extends ARRAY {
61
61
  *
62
62
  * @throws A {@link DBC.Infringement } if the **CANDIDATE** **toCheck** does not fulfill this {@link PLAIN_OBJECT }. */
63
63
  static tsCheck<CANDIDATE extends object = object>(toCheck: CANDIDATE | undefined | null, hint?: string | undefined, id?: string | undefined, dbc?: string | undefined): CANDIDATE;
64
- /**
65
- * Creates this {@link PLAIN_OBJECT } instance. No parameters needed — the check is always the same. */
66
- constructor();
67
64
  }
@@ -0,0 +1,95 @@
1
+ import { DBC } from "../../DBC";
2
+ import { ARRAY } from "../ARRAY";
3
+ /**
4
+ * A {@link DBC } defining that a value must be a plain object — i.e. `typeof value === "object"`,
5
+ * not `null`, and not an array.
6
+ *
7
+ * @remarks
8
+ * Maintainer: Salvatore Callari (XDBC@WaXCode.net) */
9
+ export class PLAIN_OBJECT extends ARRAY {
10
+ /**
11
+ * Checks if the value **toCheck** is a plain object (non-null, non-array object).
12
+ *
13
+ * @param toCheck The value to check.
14
+ *
15
+ * @returns TRUE if the value **toCheck** is a plain object, otherwise a string describing the infringement. */
16
+ static checkAlgorithm(toCheck) {
17
+ if (toCheck === undefined || toCheck === null)
18
+ return true;
19
+ if (typeof toCheck !== "object") {
20
+ return `Value has to be a PLAIN_OBJECT but is of type "${typeof toCheck}"`;
21
+ }
22
+ if (Array.isArray(toCheck)) {
23
+ return "Value has to be a PLAIN_OBJECT but is an ARRAY";
24
+ }
25
+ return true;
26
+ }
27
+ /**
28
+ * A parameter-decorator factory using the {@link PLAIN_OBJECT.checkAlgorithm } to determine whether this {@link DBC } is fulfilled
29
+ * by the tagged parameter.
30
+ *
31
+ * @param path See {@link DBC.decPrecondition }.
32
+ * @param hint See {@link DBC.decPrecondition }.
33
+ * @param dbc See {@link DBC.decPrecondition }.
34
+ *
35
+ * @returns See {@link DBC.decPrecondition }. */
36
+ static PRE(path = undefined, hint = undefined, dbc = undefined) {
37
+ return DBC.createPRE(PLAIN_OBJECT.checkAlgorithm, [], dbc, path, hint);
38
+ }
39
+ /**
40
+ * A method-decorator factory using the {@link PLAIN_OBJECT.checkAlgorithm } to determine whether this {@link DBC } is fulfilled
41
+ * by the tagged method's returnvalue.
42
+ *
43
+ * @param path See {@link DBC.decPostcondition }.
44
+ * @param hint See {@link DBC.decPostcondition }.
45
+ * @param dbc See {@link DBC.decPostcondition }.
46
+ *
47
+ * @returns See {@link DBC.decPostcondition }. */
48
+ static POST(path = undefined, hint = undefined, dbc = undefined) {
49
+ return DBC.createPOST(PLAIN_OBJECT.checkAlgorithm, [], dbc, path, hint);
50
+ }
51
+ /**
52
+ * A field-decorator factory using the {@link PLAIN_OBJECT.checkAlgorithm } to determine whether this {@link DBC } is fulfilled
53
+ * by the tagged field.
54
+ *
55
+ * @param path See {@link DBC.decInvariant }.
56
+ * @param hint See {@link DBC.decInvariant }.
57
+ * @param dbc See {@link DBC.decInvariant }.
58
+ *
59
+ * @returns See {@link DBC.decInvariant }. */
60
+ static INVARIANT(path = undefined, hint = undefined, dbc = undefined) {
61
+ return DBC.createINVARIANT(PLAIN_OBJECT, [], dbc, path, hint);
62
+ }
63
+ // #endregion Condition checking.
64
+ // #region Referenced Condition checking.
65
+ //
66
+ // For usage in dynamic scenarios (like with AE-DBC).
67
+ //
68
+ /**
69
+ * Invokes the {@link PLAIN_OBJECT.checkAlgorithm } passing the value **toCheck**.
70
+ *
71
+ * @param toCheck See {@link PLAIN_OBJECT.checkAlgorithm }.
72
+ *
73
+ * @returns See {@link PLAIN_OBJECT.checkAlgorithm}. */
74
+ check(toCheck) {
75
+ return PLAIN_OBJECT.checkAlgorithm(toCheck);
76
+ }
77
+ /**
78
+ * Invokes the {@link PLAIN_OBJECT.checkAlgorithm } passing the value **toCheck**.
79
+ *
80
+ * @param toCheck See {@link PLAIN_OBJECT.checkAlgorithm }.
81
+ * @param hint An optional {@link string } providing extra information in case of an infringement.
82
+ * @param id A {@link string } identifying this {@link PLAIN_OBJECT } via the {@link DBC.Infringement }-Message.
83
+ *
84
+ * @returns The **CANDIDATE** **toCheck** if this {@link PLAIN_OBJECT } is fulfilled.
85
+ *
86
+ * @throws A {@link DBC.Infringement } if the **CANDIDATE** **toCheck** does not fulfill this {@link PLAIN_OBJECT }. */
87
+ static tsCheck(toCheck, hint = undefined, id = undefined, dbc = undefined) {
88
+ const result = PLAIN_OBJECT.checkAlgorithm(toCheck);
89
+ if (result === true) {
90
+ return toCheck;
91
+ }
92
+ DBC.reportTsCheckInfringement(`${id ? `(${id}) ` : ""}${result}${hint ? ` ✨ ${hint} ✨` : ""}`, dbc);
93
+ return toCheck;
94
+ }
95
+ }
@@ -60,7 +60,4 @@ export declare class ARRAY extends DBC {
60
60
  *
61
61
  * @throws A {@link DBC.Infringement } if the **CANDIDATE** **toCheck** does not fulfill this {@link ARRAY }. */
62
62
  static tsCheck<CANDIDATE extends unknown[] = unknown[]>(toCheck: CANDIDATE | undefined | null, hint?: string | undefined, id?: string | undefined, dbc?: string | undefined): CANDIDATE;
63
- /**
64
- * Creates this {@link ARRAY } instance. No parameters needed — the check is always {@link Array.isArray }. */
65
- constructor();
66
63
  }