xdbc 1.0.96 → 1.0.98
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/package.json +1 -1
- package/src/DBC/HasAttribute.ts +17 -0
- package/src/DBC/IF.ts +147 -0
- package/src/DBC.ts +83 -0
package/package.json
CHANGED
package/src/DBC/HasAttribute.ts
CHANGED
|
@@ -109,6 +109,23 @@ export class HasAttribute extends DBC {
|
|
|
109
109
|
) {
|
|
110
110
|
return DBC.decInvariant([new HasAttribute(toCheckFor, invert)], path, dbc);
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* A field-decorator factory using the {@link hasAttribute.checkAlgorithm } to determine whether this {@link DBC } is
|
|
114
|
+
* fulfilled by the tagged field's class instance.
|
|
115
|
+
*
|
|
116
|
+
* @param toCheckFor See {@link hasAttribute.checkAlgorithm }.
|
|
117
|
+
* @param path See {@link DBC.decInvariant }.
|
|
118
|
+
* @param dbc See {@link DBC.decInvariant }.
|
|
119
|
+
*
|
|
120
|
+
* @returns See {@link DBC.decInvariant }. */
|
|
121
|
+
public static cINVARIANT(
|
|
122
|
+
toCheckFor: any,
|
|
123
|
+
invert = false,
|
|
124
|
+
path: string | undefined = undefined,
|
|
125
|
+
dbc = "WaXCode.DBC",
|
|
126
|
+
) {
|
|
127
|
+
return DBC.decClassInvariant([new HasAttribute(toCheckFor, invert)], path, dbc);
|
|
128
|
+
}
|
|
112
129
|
// #endregion Condition checking.
|
|
113
130
|
// #region Referenced Condition checking.
|
|
114
131
|
//
|
package/src/DBC/IF.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { DBC } from "../DBC";
|
|
2
|
+
/**
|
|
3
|
+
* A {@link DBC } defining that an {@link object } has also to comply to a certain {@link DBC } if it complies to
|
|
4
|
+
* another specified one.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Maintainer: Callari, Salvatore (XDBC@WaXCode.net) */
|
|
8
|
+
export class IF extends DBC {
|
|
9
|
+
// #region Condition checking.
|
|
10
|
+
/**
|
|
11
|
+
* Checks if the value **toCheck** complies to the specified **condition** and if so does also comply to the one **inCase**.
|
|
12
|
+
*
|
|
13
|
+
* @param toCheck The value that has to be equal to it's possible **equivalent** for this {@link DBC } to be fulfilled.
|
|
14
|
+
* @param condition The contract **toCheck** has to comply to in order to also have to comply to the one **inCase**.
|
|
15
|
+
* @param inCase The contract **toCheck** has to also comply to if it complies to **condition**.
|
|
16
|
+
*
|
|
17
|
+
* @returns TRUE if the value **toCheck** and the **equivalent** are equal to each other, otherwise FALSE. */
|
|
18
|
+
public static checkAlgorithm(
|
|
19
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
20
|
+
toCheck: any,
|
|
21
|
+
condition: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
22
|
+
inCase:{
|
|
23
|
+
check: (toCheck: unknown | undefined | null | object) => boolean | string;
|
|
24
|
+
},
|
|
25
|
+
invert,
|
|
26
|
+
): boolean | string {
|
|
27
|
+
if (!invert && condition.check(toCheck)&&!inCase.check(toCheck)) {
|
|
28
|
+
return `In case that the value complies to "${condition}" it also has to comply to "${inCase}"`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!invert && !condition.check(toCheck)&&!inCase.check(toCheck)) {
|
|
32
|
+
return `In case that the value does not comply to "${condition}" it has to comply to "${inCase}"`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A parameter-decorator factory using the {@link EQ.checkAlgorithm } to determine whether this {@link DBC } is fulfilled
|
|
39
|
+
* by the tagged parameter.
|
|
40
|
+
*
|
|
41
|
+
* @param condition See {@link IF.checkAlgorithm }.
|
|
42
|
+
* @param inCase See {@link IF.checkAlgorithm }.
|
|
43
|
+
* @param path See {@link DBC.decPrecondition }.
|
|
44
|
+
* @param dbc See {@link DBC.decPrecondition }.
|
|
45
|
+
*
|
|
46
|
+
* @returns See {@link DBC.decPrecondition }. */
|
|
47
|
+
public static PRE(
|
|
48
|
+
condition: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
49
|
+
inCase: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
50
|
+
invert = false,
|
|
51
|
+
path: string | undefined = undefined,
|
|
52
|
+
dbc = "WaXCode.DBC",
|
|
53
|
+
): (
|
|
54
|
+
target: object,
|
|
55
|
+
methodName: string | symbol,
|
|
56
|
+
parameterIndex: number,
|
|
57
|
+
) => void {
|
|
58
|
+
return DBC.decPrecondition(
|
|
59
|
+
(
|
|
60
|
+
value: object,
|
|
61
|
+
target: object,
|
|
62
|
+
methodName: string,
|
|
63
|
+
parameterIndex: number,
|
|
64
|
+
) => {
|
|
65
|
+
return IF.checkAlgorithm(value, condition, inCase, invert);
|
|
66
|
+
},
|
|
67
|
+
dbc,
|
|
68
|
+
path,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A method-decorator factory using the {@link IF.checkAlgorithm } to determine whether this {@link DBC } is fulfilled
|
|
73
|
+
* by the tagged method's returnvalue.
|
|
74
|
+
*
|
|
75
|
+
* @param condition See {@link IF.checkAlgorithm }.
|
|
76
|
+
* @param inCase See {@link IF.checkAlgorithm }.
|
|
77
|
+
* @param path See {@link DBC.Postcondition }.
|
|
78
|
+
* @param dbc See {@link DBC.decPostcondition }.
|
|
79
|
+
*
|
|
80
|
+
* @returns See {@link DBC.decPostcondition }. */
|
|
81
|
+
public static POST(
|
|
82
|
+
condition: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
83
|
+
inCase: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
84
|
+
invert = false,
|
|
85
|
+
path: string | undefined = undefined,
|
|
86
|
+
dbc = "WaXCode.DBC",
|
|
87
|
+
): (
|
|
88
|
+
target: object,
|
|
89
|
+
propertyKey: string,
|
|
90
|
+
descriptor: PropertyDescriptor,
|
|
91
|
+
) => PropertyDescriptor {
|
|
92
|
+
return DBC.decPostcondition(
|
|
93
|
+
(value: object, target: object, propertyKey: string) => {
|
|
94
|
+
return IF.checkAlgorithm(value, condition, inCase, invert);
|
|
95
|
+
},
|
|
96
|
+
dbc,
|
|
97
|
+
path,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* A field-decorator factory using the {@link IF.checkAlgorithm } to determine whether this {@link DBC } is fulfilled
|
|
102
|
+
* by the tagged field.
|
|
103
|
+
*
|
|
104
|
+
* @param condition See {@link IF.checkAlgorithm }.
|
|
105
|
+
* @param inCase See {@link IF.checkAlgorithm }.
|
|
106
|
+
* @param path See {@link DBC.decInvariant }.
|
|
107
|
+
* @param dbc See {@link DBC.decInvariant }.
|
|
108
|
+
*
|
|
109
|
+
* @returns See {@link DBC.decInvariant }. */
|
|
110
|
+
public static INVARIANT(
|
|
111
|
+
condition: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
112
|
+
inCase: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
113
|
+
invert = false,
|
|
114
|
+
path: string | undefined = undefined,
|
|
115
|
+
dbc = "WaXCode.DBC",
|
|
116
|
+
) {
|
|
117
|
+
return DBC.decInvariant([new IF(condition, inCase, invert)], path, dbc);
|
|
118
|
+
}
|
|
119
|
+
// #endregion Condition checking.
|
|
120
|
+
// #region Referenced Condition checking.
|
|
121
|
+
//
|
|
122
|
+
// For usage in dynamic scenarios (like with AE-DBC).
|
|
123
|
+
//
|
|
124
|
+
/**
|
|
125
|
+
* Invokes the {@link IF.checkAlgorithm } passing the value **toCheck**, {@link IF.equivalent } and {@link IF.invert }.
|
|
126
|
+
*
|
|
127
|
+
* @param toCheck See {@link IF.checkAlgorithm }.
|
|
128
|
+
*
|
|
129
|
+
* @returns See {@link IF.checkAlgorithm}. */
|
|
130
|
+
// biome-ignore lint/suspicious/noExplicitAny: Necessary to check against NULL & UNDEFINED.
|
|
131
|
+
public check(toCheck: any) {
|
|
132
|
+
return IF.checkAlgorithm(toCheck, this.condition, this.inCase, this.invert);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Creates this {@link IF } by setting the protected property {@link IF.equivalent } used by {@link IF.check }.
|
|
136
|
+
*
|
|
137
|
+
* @param equivalent See {@link IF.check }. */
|
|
138
|
+
public constructor(
|
|
139
|
+
// biome-ignore lint/suspicious/noExplicitAny: To be able to match UNDEFINED and NULL.
|
|
140
|
+
protected condition: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
141
|
+
protected inCase: {check: (toCheck: unknown | undefined | null | object) => boolean | string;},
|
|
142
|
+
protected invert = false,
|
|
143
|
+
) {
|
|
144
|
+
super();
|
|
145
|
+
}
|
|
146
|
+
// #endregion Referenced Condition checking.
|
|
147
|
+
}
|
package/src/DBC.ts
CHANGED
|
@@ -123,6 +123,89 @@ export class DBC {
|
|
|
123
123
|
return descriptor;
|
|
124
124
|
}
|
|
125
125
|
// #endregion Parameter-value requests.
|
|
126
|
+
// #region Class
|
|
127
|
+
/**
|
|
128
|
+
* A property-decorator factory serving as a **D**esign **B**y **C**ontract Invariant.
|
|
129
|
+
* This invariant aims to check the instance of the class not the value to be get or set.
|
|
130
|
+
*
|
|
131
|
+
* @param contracts The {@link DBC }-Contracts the value shall uphold.
|
|
132
|
+
*
|
|
133
|
+
* @throws A {@link DBC.Infringement } whenever the property is tried to be get or set without the instance of it's class
|
|
134
|
+
* fulfilling the specified **contracts**. */
|
|
135
|
+
public static decClassInvariant(
|
|
136
|
+
contracts: Array<{
|
|
137
|
+
check: (toCheck: unknown | null | undefined) => boolean | string;
|
|
138
|
+
}>,
|
|
139
|
+
path: string | undefined = undefined,
|
|
140
|
+
dbc = "WaXCode.DBC",
|
|
141
|
+
) {
|
|
142
|
+
return (target: unknown, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
|
|
143
|
+
if (!DBC.resolveDBCPath(window, dbc).executionSettings.checkInvariants) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const originalSetter = descriptor.set;
|
|
147
|
+
const originalGetter = descriptor.get;
|
|
148
|
+
// biome-ignore lint/suspicious/noExplicitAny: Necessary to intercept UNDEFINED and NULL.
|
|
149
|
+
let value: any;
|
|
150
|
+
// #region Replace original property.
|
|
151
|
+
Object.defineProperty(target, propertyKey, {
|
|
152
|
+
get() {
|
|
153
|
+
if (
|
|
154
|
+
!DBC.resolveDBCPath(window, dbc).executionSettings.checkInvariants
|
|
155
|
+
) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const realValue = path ? DBC.resolve(this, path) : this;
|
|
160
|
+
// #region Check if all "contracts" are fulfilled.
|
|
161
|
+
for (const contract of contracts) {
|
|
162
|
+
const result = contract.check(realValue);
|
|
163
|
+
|
|
164
|
+
if (typeof result === "string") {
|
|
165
|
+
DBC.resolveDBCPath(window, dbc).reportFieldInfringement(
|
|
166
|
+
result,
|
|
167
|
+
target as object,
|
|
168
|
+
path,
|
|
169
|
+
propertyKey as string,
|
|
170
|
+
realValue,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// #endregion Check if all "contracts" are fulfilled.
|
|
175
|
+
return originalGetter[ propertyKey ];
|
|
176
|
+
},
|
|
177
|
+
set(newValue) {
|
|
178
|
+
if (
|
|
179
|
+
!DBC.resolveDBCPath(window, dbc).executionSettings.checkInvariants
|
|
180
|
+
) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const realValue = path ? DBC.resolve(this, path) : this;
|
|
185
|
+
// #region Check if all "contracts" are fulfilled.
|
|
186
|
+
for (const contract of contracts) {
|
|
187
|
+
const result = contract.check(realValue);
|
|
188
|
+
|
|
189
|
+
if (typeof result === "string") {
|
|
190
|
+
DBC.resolveDBCPath(window, dbc).reportFieldInfringement(
|
|
191
|
+
result,
|
|
192
|
+
target as object,
|
|
193
|
+
path,
|
|
194
|
+
propertyKey as string,
|
|
195
|
+
realValue,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// #endregion Check if all "contracts" are fulfilled.
|
|
200
|
+
value = newValue;
|
|
201
|
+
},
|
|
202
|
+
enumerable: true,
|
|
203
|
+
configurable: true,
|
|
204
|
+
});
|
|
205
|
+
// #endregion Replace original property.
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// #endregion Class
|
|
126
209
|
// #region Invariant
|
|
127
210
|
/**
|
|
128
211
|
* A property-decorator factory serving as a **D**esign **B**y **C**ontract Invariant.
|