@flusys/nestjs-entity-builder 9.1.1 → 9.2.0
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/README.md +24 -12
- package/config/message-keys.d.ts +29 -0
- package/controllers/entity-definition.controller.d.ts +1 -0
- package/controllers/field-definition.controller.d.ts +1 -0
- package/controllers/flow-definition.controller.d.ts +1 -0
- package/dtos/definition-bundle.dto.d.ts +1 -0
- package/dtos/entity-definition.dto.d.ts +1 -2
- package/fesm/21.js +31 -2
- package/fesm/458.js +8 -3
- package/fesm/677.js +890 -465
- package/fesm/{582.js → 857.js} +201 -265
- package/fesm/870.js +580 -247
- package/fesm/897.js +164 -22
- package/fesm/946.js +5 -1
- package/fesm/controllers/index.js +1 -1
- package/fesm/dtos/index.js +11 -0
- package/fesm/guards/index.js +2 -2
- package/fesm/index.js +39 -6
- package/fesm/interfaces/index.js +74 -3
- package/fesm/modules/index.js +1 -1
- package/fesm/rule-engine/index.js +2 -2
- package/fesm/services/index.js +13 -3
- package/flow-engine/flow-input.validator.d.ts +2 -1
- package/flow-engine/flow-run.types.d.ts +1 -0
- package/flow-engine/flow.types.d.ts +25 -4
- package/interfaces/definition-bundle.interface.d.ts +2 -1
- package/interfaces/generic-record.interface.d.ts +11 -1
- package/package.json +3 -4
- package/rule-engine/rule-engine.service.d.ts +2 -1
- package/rule-engine/rule-regex.d.ts +0 -2
- package/rule-engine/rule-values.d.ts +4 -1
- package/rule-engine/rule.interface.d.ts +2 -3
- package/services/definition-bundle.diff.d.ts +6 -0
- package/services/definition-bundle.service.d.ts +10 -2
- package/services/entity-flow-scaffold.d.ts +2 -1
- package/services/entity-permission.service.d.ts +1 -0
- package/services/flow-definition.service.d.ts +1 -1
- package/services/flow-runtime.service.d.ts +1 -0
- package/services/generic-entity.service.d.ts +5 -0
- package/services/schema-change-executor.service.d.ts +1 -0
- package/services/schema-dialect-adapter.service.d.ts +2 -0
package/fesm/{582.js → 857.js}
RENAMED
|
@@ -1,24 +1,79 @@
|
|
|
1
|
-
import { RE2JS } from "re2js";
|
|
2
1
|
import * as __rspack_external__flusys_nestjs_shared_interfaces_413f2706 from "@flusys/nestjs-shared/interfaces";
|
|
3
2
|
import * as __rspack_external__flusys_nestjs_shared_modules_24702bee from "@flusys/nestjs-shared/modules";
|
|
4
3
|
import * as __rspack_external__flusys_nestjs_shared_utils_9125c1f1 from "@flusys/nestjs-shared/utils";
|
|
5
4
|
import * as __rspack_external__nestjs_common_a04939da from "@nestjs/common";
|
|
6
5
|
import * as __rspack_external_node_net_5ed819e1 from "node:net";
|
|
7
|
-
export const __rspack_esm_id =
|
|
8
|
-
export const __rspack_esm_ids = [
|
|
6
|
+
export const __rspack_esm_id = 857;
|
|
7
|
+
export const __rspack_esm_ids = [857];
|
|
9
8
|
export const __webpack_modules__ = {
|
|
10
9
|
3372(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
11
10
|
const RECORD_FILTER_OPS = [
|
|
12
11
|
'eq',
|
|
13
12
|
'ne',
|
|
13
|
+
'ieq',
|
|
14
14
|
'gt',
|
|
15
15
|
'gte',
|
|
16
16
|
'lt',
|
|
17
17
|
'lte',
|
|
18
|
+
'between',
|
|
19
|
+
'not_between',
|
|
18
20
|
'in',
|
|
21
|
+
'not_in',
|
|
22
|
+
'contains',
|
|
23
|
+
'not_contains',
|
|
24
|
+
'starts_with',
|
|
25
|
+
'ends_with',
|
|
26
|
+
'has_any',
|
|
27
|
+
'has_all',
|
|
28
|
+
'has_none',
|
|
29
|
+
'is_empty',
|
|
30
|
+
'not_empty',
|
|
19
31
|
'is_null',
|
|
20
32
|
'not_null'
|
|
21
33
|
];
|
|
34
|
+
const FILTER_OP_VALUE_KIND = {
|
|
35
|
+
eq: 'single',
|
|
36
|
+
ne: 'single',
|
|
37
|
+
ieq: 'single',
|
|
38
|
+
gt: 'single',
|
|
39
|
+
gte: 'single',
|
|
40
|
+
lt: 'single',
|
|
41
|
+
lte: 'single',
|
|
42
|
+
between: 'range',
|
|
43
|
+
not_between: 'range',
|
|
44
|
+
in: 'list',
|
|
45
|
+
not_in: 'list',
|
|
46
|
+
contains: 'single',
|
|
47
|
+
not_contains: 'single',
|
|
48
|
+
starts_with: 'single',
|
|
49
|
+
ends_with: 'single',
|
|
50
|
+
has_any: 'list',
|
|
51
|
+
has_all: 'list',
|
|
52
|
+
has_none: 'list',
|
|
53
|
+
is_empty: 'none',
|
|
54
|
+
not_empty: 'none',
|
|
55
|
+
is_null: 'none',
|
|
56
|
+
not_null: 'none'
|
|
57
|
+
};
|
|
58
|
+
/** Case-insensitive text operators: text, long text, email and single-select fields only. */ const TEXT_FILTER_OPS = [
|
|
59
|
+
'ieq',
|
|
60
|
+
'contains',
|
|
61
|
+
'not_contains',
|
|
62
|
+
'starts_with',
|
|
63
|
+
'ends_with'
|
|
64
|
+
];
|
|
65
|
+
/** Multi-select operators: whether the stored list holds any / all / none of the given values. */ const LIST_FIELD_FILTER_OPS = [
|
|
66
|
+
'has_any',
|
|
67
|
+
'has_all',
|
|
68
|
+
'has_none'
|
|
69
|
+
];
|
|
70
|
+
/** Blank checks: no value, an empty text or an empty multi-select. */ const EMPTY_FILTER_OPS = [
|
|
71
|
+
'is_empty',
|
|
72
|
+
'not_empty'
|
|
73
|
+
];
|
|
74
|
+
function isFilterRange(value) {
|
|
75
|
+
return !!value && typeof value === 'object' && !Array.isArray(value) && 'from' in value && 'to' in value && Object.keys(value).length === 2;
|
|
76
|
+
}
|
|
22
77
|
const RECORD_FILTER_LIMITS = {
|
|
23
78
|
MAX_IN_VALUES: 100
|
|
24
79
|
};
|
|
@@ -37,15 +92,20 @@ const FILTER_CONDITION_KEYS = new Set([
|
|
|
37
92
|
}
|
|
38
93
|
|
|
39
94
|
__webpack_require__.d(__webpack_exports__, {
|
|
95
|
+
iA: () => (isFilterRange),
|
|
40
96
|
t1: () => (isRecordFilterCondition)
|
|
41
97
|
}, {
|
|
42
98
|
M5: RECORD_FILTER_LIMITS,
|
|
43
|
-
|
|
99
|
+
Oh: EMPTY_FILTER_OPS,
|
|
100
|
+
ox: RECORD_FILTER_OPS,
|
|
101
|
+
w9: FILTER_OP_VALUE_KIND,
|
|
102
|
+
wk: TEXT_FILTER_OPS,
|
|
103
|
+
yV: LIST_FIELD_FILTER_OPS
|
|
44
104
|
});
|
|
45
105
|
|
|
46
106
|
|
|
47
107
|
},
|
|
48
|
-
|
|
108
|
+
8552(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
49
109
|
|
|
50
110
|
// EXPORTS
|
|
51
111
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -74,14 +134,87 @@ var common_ = __webpack_require__(6157);
|
|
|
74
134
|
var external_node_crypto_ = __webpack_require__(2561);
|
|
75
135
|
// EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/config/message-keys.ts
|
|
76
136
|
var message_keys = __webpack_require__(5732);
|
|
77
|
-
// EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/interfaces/generic-record.interface.ts
|
|
78
|
-
var generic_record_interface = __webpack_require__(3372);
|
|
79
137
|
// EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-ip.ts
|
|
80
138
|
var rule_ip = __webpack_require__(809);
|
|
81
139
|
// EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-permission.ts
|
|
82
140
|
var rule_permission = __webpack_require__(5191);
|
|
83
|
-
|
|
84
|
-
|
|
141
|
+
;// CONCATENATED MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-regex.ts
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
/** RE2 (linear-time) search: true when the pattern matches anywhere in the input. */ function matchesPattern(input, pattern) {
|
|
147
|
+
const prepared = prepare(input, pattern);
|
|
148
|
+
return prepared ? prepared.regex.matcher(prepared.text).find() : false;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The first match's capture `group` (default: the first group when the pattern has one, else the
|
|
152
|
+
* whole match); null when nothing matches or the group does not exist.
|
|
153
|
+
*/ function extractPattern(input, pattern, group) {
|
|
154
|
+
const prepared = prepare(input, pattern);
|
|
155
|
+
if (!prepared) return null;
|
|
156
|
+
const index = group === undefined || group === null || group === '' ? prepared.regex.groupCount() > 0 ? 1 : 0 : Number(group);
|
|
157
|
+
if (!Number.isInteger(index) || index < 0 || index > prepared.regex.groupCount()) return null;
|
|
158
|
+
const matcher = prepared.regex.matcher(prepared.text);
|
|
159
|
+
return matcher.find() ? matcher.group(index) ?? null : null;
|
|
160
|
+
}
|
|
161
|
+
function prepare(input, pattern) {
|
|
162
|
+
if (typeof pattern !== 'string') {
|
|
163
|
+
throw new common_.BadRequestException({
|
|
164
|
+
message: 'A regular expression pattern must be text.',
|
|
165
|
+
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INVALID */.x3.REGEX_INVALID,
|
|
166
|
+
messageVariables: {
|
|
167
|
+
pattern: JSON.stringify(pattern ?? null)
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
const problem = (0,utils_.safeRegexProblem)(pattern);
|
|
172
|
+
if (problem) throw patternError(problem, pattern);
|
|
173
|
+
const text = typeof input === 'string' ? input : typeof input === 'number' || typeof input === 'boolean' ? String(input) : null;
|
|
174
|
+
if (text === null) return null;
|
|
175
|
+
if (text.length > rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_INPUT_LENGTH */.bw.MAX_REGEX_INPUT_LENGTH) {
|
|
176
|
+
throw new common_.BadRequestException({
|
|
177
|
+
message: `Text matched against a regular expression can be at most ${rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_INPUT_LENGTH */.bw.MAX_REGEX_INPUT_LENGTH} characters.`,
|
|
178
|
+
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INPUT_TOO_LONG */.x3.REGEX_INPUT_TOO_LONG,
|
|
179
|
+
messageVariables: {
|
|
180
|
+
max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_INPUT_LENGTH */.bw.MAX_REGEX_INPUT_LENGTH
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
regex: (0,utils_.compileSafeRegex)(pattern),
|
|
186
|
+
text
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function patternError(problem, pattern) {
|
|
190
|
+
switch(problem){
|
|
191
|
+
case 'too_long':
|
|
192
|
+
return new common_.BadRequestException({
|
|
193
|
+
message: `A regular expression pattern can be at most ${rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_PATTERN_LENGTH */.bw.MAX_REGEX_PATTERN_LENGTH} characters.`,
|
|
194
|
+
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_PATTERN_TOO_LONG */.x3.REGEX_PATTERN_TOO_LONG,
|
|
195
|
+
messageVariables: {
|
|
196
|
+
max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_PATTERN_LENGTH */.bw.MAX_REGEX_PATTERN_LENGTH
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
case 'too_complex':
|
|
200
|
+
return new common_.BadRequestException({
|
|
201
|
+
message: `A regular expression can repeat a part at most ${rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_REPEAT */.bw.MAX_REGEX_REPEAT} times, nested repeats included.`,
|
|
202
|
+
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_TOO_COMPLEX */.x3.REGEX_TOO_COMPLEX,
|
|
203
|
+
messageVariables: {
|
|
204
|
+
max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_REPEAT */.bw.MAX_REGEX_REPEAT
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
case 'invalid':
|
|
208
|
+
return new common_.BadRequestException({
|
|
209
|
+
message: `'${pattern}' is not a valid regular expression.`,
|
|
210
|
+
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INVALID */.x3.REGEX_INVALID,
|
|
211
|
+
messageVariables: {
|
|
212
|
+
pattern
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
85
218
|
// EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-values.ts
|
|
86
219
|
var rule_values = __webpack_require__(6622);
|
|
87
220
|
;// CONCATENATED MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-engine.service.ts
|
|
@@ -119,7 +252,6 @@ function _ts_param(paramIndex, decorator) {
|
|
|
119
252
|
|
|
120
253
|
|
|
121
254
|
|
|
122
|
-
|
|
123
255
|
const FORBIDDEN_PATH_KEYS = new Set([
|
|
124
256
|
'__proto__',
|
|
125
257
|
'constructor',
|
|
@@ -145,6 +277,12 @@ class RuleEngineService {
|
|
|
145
277
|
cache: this.permissionCache
|
|
146
278
|
});
|
|
147
279
|
}
|
|
280
|
+
/** Any user's codes in any company / branch - another user, or the caller outside their current scope. */ permissionCodes(scope) {
|
|
281
|
+
return (0,utils_.loadPermissionCodes)(scope, {
|
|
282
|
+
resolver: this.permissionResolver,
|
|
283
|
+
cache: this.permissionCache
|
|
284
|
+
});
|
|
285
|
+
}
|
|
148
286
|
async evaluateGroup(group, ctx, depth = 0, budget = {}) {
|
|
149
287
|
this.assertWithinLimits(group, depth);
|
|
150
288
|
const evaluate = (node)=>(0,rule_interface/* .isRuleGroup */.GD)(node) ? this.evaluateGroup(node, ctx, depth + 1, budget) : this.evaluateCondition(node, ctx, budget);
|
|
@@ -221,9 +359,9 @@ class RuleEngineService {
|
|
|
221
359
|
case 'is_false':
|
|
222
360
|
return actual === false;
|
|
223
361
|
case 'matches':
|
|
224
|
-
return
|
|
362
|
+
return matchesPattern(actual, expected);
|
|
225
363
|
case 'not_matches':
|
|
226
|
-
return !
|
|
364
|
+
return !matchesPattern(actual, expected);
|
|
227
365
|
}
|
|
228
366
|
}
|
|
229
367
|
async resolveConditionLeft(condition, ctx, budget) {
|
|
@@ -290,17 +428,7 @@ class RuleEngineService {
|
|
|
290
428
|
}
|
|
291
429
|
const filter = {};
|
|
292
430
|
for (const [key, item] of Object.entries(expression.filter ?? {})){
|
|
293
|
-
|
|
294
|
-
const value = item.value === undefined ? undefined : await this.resolveExpression(item.value, ctx, budget);
|
|
295
|
-
filter[key] = value === undefined ? {
|
|
296
|
-
op: item.op
|
|
297
|
-
} : {
|
|
298
|
-
op: item.op,
|
|
299
|
-
value
|
|
300
|
-
};
|
|
301
|
-
} else {
|
|
302
|
-
filter[key] = (0,rule_values/* .equalsOperand */.$b)(await this.resolveExpression(item, ctx, budget));
|
|
303
|
-
}
|
|
431
|
+
filter[key] = await (0,rule_values/* .resolveFilterEntry */.vY)(item, (value)=>this.resolveExpression(value, ctx, budget));
|
|
304
432
|
}
|
|
305
433
|
const { rows, total } = await ctx.lookupResolver.find(expression.entity, {
|
|
306
434
|
filter,
|
|
@@ -469,14 +597,15 @@ class RuleEngineService {
|
|
|
469
597
|
return part === undefined ? null : part.trim();
|
|
470
598
|
}
|
|
471
599
|
case 'REGEX_EXTRACT':
|
|
472
|
-
return
|
|
600
|
+
return extractPattern(resolvedArgs[0], resolvedArgs[1], resolvedArgs[2]);
|
|
473
601
|
case 'REPLACE':
|
|
474
602
|
{
|
|
475
603
|
const [value, search, replacement] = resolvedArgs;
|
|
476
604
|
const text = this.toText(value);
|
|
477
605
|
if (text === null) return null;
|
|
478
606
|
const needle = this.toText(search) ?? '';
|
|
479
|
-
|
|
607
|
+
const replacementText = this.toText(replacement) ?? '';
|
|
608
|
+
return needle ? text.replaceAll(needle, ()=>replacementText) : text;
|
|
480
609
|
}
|
|
481
610
|
case 'TO_NUMBER':
|
|
482
611
|
{
|
|
@@ -824,235 +953,10 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
824
953
|
});
|
|
825
954
|
|
|
826
955
|
|
|
827
|
-
},
|
|
828
|
-
6308(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
829
|
-
|
|
830
|
-
// EXPORTS
|
|
831
|
-
__webpack_require__.d(__webpack_exports__, {
|
|
832
|
-
Ax: () => (/* binding */ extractPattern),
|
|
833
|
-
MT: () => (/* binding */ matchesPattern),
|
|
834
|
-
_V: () => (/* binding */ rulePatternProblem)
|
|
835
|
-
});
|
|
836
|
-
|
|
837
|
-
// EXTERNAL MODULE: external "@nestjs/common"
|
|
838
|
-
var common_ = __webpack_require__(6157);
|
|
839
|
-
;// CONCATENATED MODULE: external "re2js"
|
|
840
|
-
|
|
841
|
-
// EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/config/message-keys.ts
|
|
842
|
-
var message_keys = __webpack_require__(5732);
|
|
843
|
-
// EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule.interface.ts
|
|
844
|
-
var rule_interface = __webpack_require__(2354);
|
|
845
|
-
;// CONCATENATED MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-regex.ts
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
const MAX_CACHED_PATTERNS = 200;
|
|
851
|
-
const compiled = new Map();
|
|
852
|
-
const tooComplex = new Map();
|
|
853
|
-
function remember(cache, pattern, make) {
|
|
854
|
-
if (cache.has(pattern)) return cache.get(pattern);
|
|
855
|
-
const value = make(pattern);
|
|
856
|
-
if (cache.size >= MAX_CACHED_PATTERNS) cache.delete(cache.keys().next().value);
|
|
857
|
-
cache.set(pattern, value);
|
|
858
|
-
return value;
|
|
859
|
-
}
|
|
860
|
-
/** Why a pattern cannot be used, or null when it compiles within the limits. */ function rulePatternProblem(pattern) {
|
|
861
|
-
if (pattern.length > rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_PATTERN_LENGTH */.bw.MAX_REGEX_PATTERN_LENGTH) return 'too_long';
|
|
862
|
-
if (remember(tooComplex, pattern, isTooComplex)) return 'too_complex';
|
|
863
|
-
try {
|
|
864
|
-
compile(pattern);
|
|
865
|
-
return null;
|
|
866
|
-
} catch {
|
|
867
|
-
return 'invalid';
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
const newFrame = ()=>({
|
|
871
|
-
size: 0,
|
|
872
|
-
last: 0,
|
|
873
|
-
lastProduct: 1,
|
|
874
|
-
maxProduct: 1
|
|
875
|
-
});
|
|
876
|
-
/**
|
|
877
|
-
* RE2 unrolls counted repeats (`x{2,50}` becomes 50 copies of x), so match time grows with the
|
|
878
|
-
* product of nested counts. Rejects a count above MAX_REGEX_REPEAT, nested counts whose product
|
|
879
|
-
* is above it, and a pattern whose unrolled size grows by more than MAX_REGEX_REPEAT_EXPANSION.
|
|
880
|
-
* `*`, `+` and `?` do not unroll and stay allowed, nested or not.
|
|
881
|
-
*/ function isTooComplex(pattern) {
|
|
882
|
-
const { MAX_REGEX_REPEAT, MAX_REGEX_REPEAT_EXPANSION } = rule_interface/* .RULE_ENGINE_LIMITS */.bw;
|
|
883
|
-
const stack = [
|
|
884
|
-
newFrame()
|
|
885
|
-
];
|
|
886
|
-
const top = ()=>stack[stack.length - 1];
|
|
887
|
-
let atoms = 0;
|
|
888
|
-
const atom = (size, product)=>{
|
|
889
|
-
const frame = top();
|
|
890
|
-
frame.size += size;
|
|
891
|
-
frame.last = size;
|
|
892
|
-
frame.lastProduct = product;
|
|
893
|
-
frame.maxProduct = Math.max(frame.maxProduct, product);
|
|
894
|
-
};
|
|
895
|
-
let i = 0;
|
|
896
|
-
while(i < pattern.length){
|
|
897
|
-
const c = pattern[i];
|
|
898
|
-
if (c === '\\') {
|
|
899
|
-
const next = pattern[i + 1];
|
|
900
|
-
i += 2;
|
|
901
|
-
if ((next === 'p' || next === 'P' || next === 'x') && pattern[i] === '{') i = closing(pattern, i, '}');
|
|
902
|
-
atoms++;
|
|
903
|
-
atom(1, 1);
|
|
904
|
-
} else if (c === '[') {
|
|
905
|
-
i = classEnd(pattern, i);
|
|
906
|
-
atoms++;
|
|
907
|
-
atom(1, 1);
|
|
908
|
-
} else if (c === '(') {
|
|
909
|
-
i++;
|
|
910
|
-
if (pattern[i] === '?') {
|
|
911
|
-
const flagsOnly = /^\?[a-zA-Z-]*\)/.exec(pattern.slice(i));
|
|
912
|
-
if (flagsOnly) {
|
|
913
|
-
i += flagsOnly[0].length;
|
|
914
|
-
continue;
|
|
915
|
-
}
|
|
916
|
-
const marker = /^\?(?:P?<[^>]*>|[a-zA-Z-]*:)/.exec(pattern.slice(i));
|
|
917
|
-
i += marker ? marker[0].length : 1;
|
|
918
|
-
}
|
|
919
|
-
stack.push(newFrame());
|
|
920
|
-
} else if (c === ')') {
|
|
921
|
-
i++;
|
|
922
|
-
if (stack.length === 1) continue;
|
|
923
|
-
const group = stack.pop();
|
|
924
|
-
atom(group.size, group.maxProduct);
|
|
925
|
-
} else if (c === '|') {
|
|
926
|
-
i++;
|
|
927
|
-
top().last = 0;
|
|
928
|
-
top().lastProduct = 1;
|
|
929
|
-
} else if (c === '{') {
|
|
930
|
-
const repeat = /^\{(\d+)(,(\d*))?\}\??/.exec(pattern.slice(i));
|
|
931
|
-
if (!repeat) {
|
|
932
|
-
i++;
|
|
933
|
-
atoms++;
|
|
934
|
-
atom(1, 1);
|
|
935
|
-
continue;
|
|
936
|
-
}
|
|
937
|
-
i += repeat[0].length;
|
|
938
|
-
const min = Number(repeat[1]);
|
|
939
|
-
const max = repeat[2] === undefined ? min : repeat[3] ? Number(repeat[3]) : min + 1;
|
|
940
|
-
if (min > MAX_REGEX_REPEAT || max > MAX_REGEX_REPEAT) return true;
|
|
941
|
-
const frame = top();
|
|
942
|
-
const product = frame.lastProduct * Math.max(max, 1);
|
|
943
|
-
if (product > MAX_REGEX_REPEAT) return true;
|
|
944
|
-
const extra = frame.last * (Math.max(max, 1) - 1);
|
|
945
|
-
frame.size += extra;
|
|
946
|
-
frame.last += extra;
|
|
947
|
-
frame.lastProduct = product;
|
|
948
|
-
frame.maxProduct = Math.max(frame.maxProduct, product);
|
|
949
|
-
} else {
|
|
950
|
-
i++;
|
|
951
|
-
if (c !== '*' && c !== '+' && c !== '?') {
|
|
952
|
-
atoms++;
|
|
953
|
-
atom(1, 1);
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
while(stack.length > 1){
|
|
958
|
-
const group = stack.pop();
|
|
959
|
-
atom(group.size, group.maxProduct);
|
|
960
|
-
}
|
|
961
|
-
return stack[0].size - atoms > MAX_REGEX_REPEAT_EXPANSION;
|
|
962
|
-
}
|
|
963
|
-
function closing(pattern, from, char) {
|
|
964
|
-
const end = pattern.indexOf(char, from);
|
|
965
|
-
return end < 0 ? pattern.length : end + 1;
|
|
966
|
-
}
|
|
967
|
-
function classEnd(pattern, start) {
|
|
968
|
-
let j = start + 1;
|
|
969
|
-
if (pattern[j] === '^') j++;
|
|
970
|
-
if (pattern[j] === ']') j++;
|
|
971
|
-
while(j < pattern.length && pattern[j] !== ']'){
|
|
972
|
-
if (pattern[j] === '\\') j += 2;
|
|
973
|
-
else if (pattern.startsWith('[:', j)) j = closing(pattern, j + 2, ']');
|
|
974
|
-
else j++;
|
|
975
|
-
}
|
|
976
|
-
return j + 1;
|
|
977
|
-
}
|
|
978
|
-
/** RE2 (linear-time) search: true when the pattern matches anywhere in the input. */ function matchesPattern(input, pattern) {
|
|
979
|
-
const prepared = prepare(input, pattern);
|
|
980
|
-
return prepared ? prepared.regex.matcher(prepared.text).find() : false;
|
|
981
|
-
}
|
|
982
|
-
/**
|
|
983
|
-
* The first match's capture `group` (default: the first group when the pattern has one, else the
|
|
984
|
-
* whole match); null when nothing matches or the group does not exist.
|
|
985
|
-
*/ function extractPattern(input, pattern, group) {
|
|
986
|
-
const prepared = prepare(input, pattern);
|
|
987
|
-
if (!prepared) return null;
|
|
988
|
-
const index = group === undefined || group === null || group === '' ? prepared.regex.groupCount() > 0 ? 1 : 0 : Number(group);
|
|
989
|
-
if (!Number.isInteger(index) || index < 0 || index > prepared.regex.groupCount()) return null;
|
|
990
|
-
const matcher = prepared.regex.matcher(prepared.text);
|
|
991
|
-
return matcher.find() ? matcher.group(index) ?? null : null;
|
|
992
|
-
}
|
|
993
|
-
function prepare(input, pattern) {
|
|
994
|
-
if (typeof pattern !== 'string') {
|
|
995
|
-
throw new common_.BadRequestException({
|
|
996
|
-
message: 'A regular expression pattern must be text.',
|
|
997
|
-
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INVALID */.x3.REGEX_INVALID,
|
|
998
|
-
messageVariables: {
|
|
999
|
-
pattern: JSON.stringify(pattern ?? null)
|
|
1000
|
-
}
|
|
1001
|
-
});
|
|
1002
|
-
}
|
|
1003
|
-
const problem = rulePatternProblem(pattern);
|
|
1004
|
-
if (problem) throw patternError(problem, pattern);
|
|
1005
|
-
const text = typeof input === 'string' ? input : typeof input === 'number' || typeof input === 'boolean' ? String(input) : null;
|
|
1006
|
-
if (text === null) return null;
|
|
1007
|
-
if (text.length > rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_INPUT_LENGTH */.bw.MAX_REGEX_INPUT_LENGTH) {
|
|
1008
|
-
throw new common_.BadRequestException({
|
|
1009
|
-
message: `Text matched against a regular expression can be at most ${rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_INPUT_LENGTH */.bw.MAX_REGEX_INPUT_LENGTH} characters.`,
|
|
1010
|
-
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INPUT_TOO_LONG */.x3.REGEX_INPUT_TOO_LONG,
|
|
1011
|
-
messageVariables: {
|
|
1012
|
-
max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_INPUT_LENGTH */.bw.MAX_REGEX_INPUT_LENGTH
|
|
1013
|
-
}
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
return {
|
|
1017
|
-
regex: compile(pattern),
|
|
1018
|
-
text
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
function patternError(problem, pattern) {
|
|
1022
|
-
switch(problem){
|
|
1023
|
-
case 'too_long':
|
|
1024
|
-
return new common_.BadRequestException({
|
|
1025
|
-
message: `A regular expression pattern can be at most ${rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_PATTERN_LENGTH */.bw.MAX_REGEX_PATTERN_LENGTH} characters.`,
|
|
1026
|
-
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_PATTERN_TOO_LONG */.x3.REGEX_PATTERN_TOO_LONG,
|
|
1027
|
-
messageVariables: {
|
|
1028
|
-
max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_PATTERN_LENGTH */.bw.MAX_REGEX_PATTERN_LENGTH
|
|
1029
|
-
}
|
|
1030
|
-
});
|
|
1031
|
-
case 'too_complex':
|
|
1032
|
-
return new common_.BadRequestException({
|
|
1033
|
-
message: `A regular expression can repeat a part at most ${rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_REPEAT */.bw.MAX_REGEX_REPEAT} times, nested repeats included.`,
|
|
1034
|
-
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_TOO_COMPLEX */.x3.REGEX_TOO_COMPLEX,
|
|
1035
|
-
messageVariables: {
|
|
1036
|
-
max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_REPEAT */.bw.MAX_REGEX_REPEAT
|
|
1037
|
-
}
|
|
1038
|
-
});
|
|
1039
|
-
case 'invalid':
|
|
1040
|
-
return new common_.BadRequestException({
|
|
1041
|
-
message: `'${pattern}' is not a valid regular expression.`,
|
|
1042
|
-
messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INVALID */.x3.REGEX_INVALID,
|
|
1043
|
-
messageVariables: {
|
|
1044
|
-
pattern
|
|
1045
|
-
}
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
function compile(pattern) {
|
|
1050
|
-
return remember(compiled, pattern, (p)=>RE2JS.compile(p));
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
956
|
},
|
|
1055
957
|
6622(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
958
|
+
/* import */ var _interfaces_generic_record_interface_js__rspack_import_0 = __webpack_require__(3372);
|
|
959
|
+
|
|
1056
960
|
const ISO_DATE_PREFIX = /^\s*\d{4}-\d{2}-\d{2}/;
|
|
1057
961
|
const ISO_DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:[.,](\d{1,9}))?)?)?\s*(Z|[+-]\d{2}(?::?\d{2})?)?$/i;
|
|
1058
962
|
const EXPLICIT_ZONE = /(?:\bZ|\bGMT|\bUTC|[+-]\d{2}:?\d{2})$/i;
|
|
@@ -1103,21 +1007,54 @@ function instant(value) {
|
|
|
1103
1007
|
}
|
|
1104
1008
|
const includesValue = (list, value)=>list.some((item)=>valuesEqual(item, value));
|
|
1105
1009
|
/**
|
|
1106
|
-
* A
|
|
1107
|
-
*
|
|
1108
|
-
* value
|
|
1109
|
-
|
|
1010
|
+
* A filter entry with its expressions resolved, as the entity service takes it: a plain expression
|
|
1011
|
+
* is `eq`, a `range` becomes `[from, to]`. `value` is undefined when a value it needs resolves to
|
|
1012
|
+
* undefined. A resolved value is only ever an operand, so an object or list sent as input (e.g.
|
|
1013
|
+
* `{ "op": "not_null" }`) never becomes an operator: the entity service refuses it as not a value.
|
|
1014
|
+
*/ async function resolveFilterEntry(item, resolve) {
|
|
1015
|
+
if (!(0,_interfaces_generic_record_interface_js__rspack_import_0/* .isRecordFilterCondition */.t1)(item)) return {
|
|
1110
1016
|
op: 'eq',
|
|
1111
|
-
value
|
|
1112
|
-
}
|
|
1017
|
+
value: await resolve(item)
|
|
1018
|
+
};
|
|
1019
|
+
const { op, value } = item;
|
|
1020
|
+
switch(_interfaces_generic_record_interface_js__rspack_import_0/* .FILTER_OP_VALUE_KIND */.w9[op]){
|
|
1021
|
+
case 'none':
|
|
1022
|
+
return {
|
|
1023
|
+
op
|
|
1024
|
+
};
|
|
1025
|
+
case 'range':
|
|
1026
|
+
{
|
|
1027
|
+
if (!(0,_interfaces_generic_record_interface_js__rspack_import_0/* .isFilterRange */.iA)(value)) return {
|
|
1028
|
+
op,
|
|
1029
|
+
value: undefined
|
|
1030
|
+
};
|
|
1031
|
+
const from = await resolve(value.from);
|
|
1032
|
+
const to = await resolve(value.to);
|
|
1033
|
+
return {
|
|
1034
|
+
op,
|
|
1035
|
+
value: from === undefined || to === undefined ? undefined : [
|
|
1036
|
+
from,
|
|
1037
|
+
to
|
|
1038
|
+
]
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
default:
|
|
1042
|
+
return {
|
|
1043
|
+
op,
|
|
1044
|
+
value: value === undefined ? undefined : await resolve(value)
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
/** Whether a resolved entry is missing the value its operator needs. */ const isFilterValueMissing = (entry)=>_interfaces_generic_record_interface_js__rspack_import_0/* .FILTER_OP_VALUE_KIND */.w9[entry.op] !== 'none' && entry.value === undefined;
|
|
1113
1049
|
|
|
1114
1050
|
__webpack_require__.d(__webpack_exports__, {
|
|
1115
1051
|
hz: () => (parseDateText),
|
|
1116
|
-
lu: () => (valuesEqual)
|
|
1052
|
+
lu: () => (valuesEqual),
|
|
1053
|
+
vY: () => (resolveFilterEntry)
|
|
1117
1054
|
}, {
|
|
1118
|
-
$b: equalsOperand,
|
|
1119
1055
|
XL: includesValue,
|
|
1120
|
-
YN: ISO_DATE_PREFIX
|
|
1056
|
+
YN: ISO_DATE_PREFIX,
|
|
1057
|
+
kp: isFilterValueMissing
|
|
1121
1058
|
});
|
|
1122
1059
|
|
|
1123
1060
|
|
|
@@ -1174,10 +1111,9 @@ const RULE_ENGINE_LIMITS = {
|
|
|
1174
1111
|
MAX_GROUP_DEPTH: 8,
|
|
1175
1112
|
MAX_CONDITIONS_PER_GROUP: 100,
|
|
1176
1113
|
MAX_LOOKUPS: 10,
|
|
1177
|
-
MAX_REGEX_PATTERN_LENGTH:
|
|
1178
|
-
MAX_REGEX_INPUT_LENGTH:
|
|
1179
|
-
/** Largest `{n,m}` count, also for the product of nested counts. */ MAX_REGEX_REPEAT:
|
|
1180
|
-
/** How much larger counted repeats may make the unrolled pattern than the pattern itself. */ MAX_REGEX_REPEAT_EXPANSION: 300,
|
|
1114
|
+
MAX_REGEX_PATTERN_LENGTH: _flusys_nestjs_shared_utils__rspack_import_0.SAFE_REGEX_LIMITS.MAX_PATTERN_LENGTH,
|
|
1115
|
+
MAX_REGEX_INPUT_LENGTH: _flusys_nestjs_shared_utils__rspack_import_0.SAFE_REGEX_LIMITS.MAX_INPUT_LENGTH,
|
|
1116
|
+
/** Largest `{n,m}` count, also for the product of nested counts. */ MAX_REGEX_REPEAT: _flusys_nestjs_shared_utils__rspack_import_0.SAFE_REGEX_LIMITS.MAX_REPEAT,
|
|
1181
1117
|
/** Largest `offsetMinutes` accepted by START_OF_DAY / END_OF_DAY (UTC+14 / UTC-12). */ MAX_UTC_OFFSET_MINUTES: 840,
|
|
1182
1118
|
MAX_PERMISSION_CODES: _flusys_nestjs_shared_utils__rspack_import_0.MAX_PERMISSION_LOGIC_CODES,
|
|
1183
1119
|
MAX_IP_RANGES: 100
|