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.
- package/.gitattributes +8 -0
- package/.vscode/settings.json +3 -3
- package/.vscode/tasks.json +23 -23
- package/ASSESSMENT.md +249 -0
- package/README.md +131 -1
- 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 +481 -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 +40 -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 +87 -0
- package/dist/DBC/DOM.js +223 -0
- package/dist/DBC/EQ/DIFFERENT.js +34 -0
- package/dist/DBC/EQ.js +101 -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/bundle.js +6140 -405
- package/dist/index.d.ts +22 -0
- package/dist/index.js +22 -0
- 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 +291 -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
|
@@ -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
|
+
}
|
package/dist/DBC/ARRAY.d.ts
CHANGED
|
@@ -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
|
}
|