@flusys/nestjs-entity-builder 9.1.0 → 9.1.2

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 (65) hide show
  1. package/README.md +59 -26
  2. package/config/entity-builder.constants.d.ts +2 -0
  3. package/config/message-keys.d.ts +96 -12
  4. package/controllers/definition-bundle.controller.d.ts +15 -0
  5. package/controllers/flow-definition.controller.d.ts +7 -1
  6. package/controllers/index.d.ts +1 -1
  7. package/dtos/definition-bundle.dto.d.ts +57 -0
  8. package/dtos/flow.dto.d.ts +12 -20
  9. package/dtos/index.d.ts +1 -0
  10. package/entities/flow-definition.entity.d.ts +3 -9
  11. package/entities/flow-execution.entity.d.ts +3 -0
  12. package/entities/flow-version.entity.d.ts +10 -0
  13. package/entities/index.d.ts +3 -3
  14. package/fesm/21.js +101 -16
  15. package/fesm/458.js +695 -0
  16. package/fesm/{996.js → 677.js} +1582 -1047
  17. package/fesm/794.js +135 -240
  18. package/fesm/{489.js → 857.js} +216 -289
  19. package/fesm/{719.js → 870.js} +1955 -220
  20. package/fesm/{362.js → 897.js} +566 -2
  21. package/fesm/{606.js → 946.js} +564 -290
  22. package/fesm/config/index.js +15 -2
  23. package/fesm/controllers/index.js +9 -9
  24. package/fesm/docs/index.js +7 -4
  25. package/fesm/dtos/index.js +451 -256
  26. package/fesm/entities/index.js +58 -3
  27. package/fesm/guards/index.js +101 -22
  28. package/fesm/index.js +444 -948
  29. package/fesm/interfaces/index.js +92 -4
  30. package/fesm/modules/index.js +10 -628
  31. package/fesm/rule-engine/index.js +12 -3
  32. package/fesm/services/index.js +97 -27
  33. package/flow-engine/flow-api-key.d.ts +3 -7
  34. package/flow-engine/flow-graph.validator.d.ts +4 -2
  35. package/flow-engine/flow-permission-logic.d.ts +2 -0
  36. package/flow-engine/flow-run.types.d.ts +17 -8
  37. package/flow-engine/flow.types.d.ts +107 -15
  38. package/guards/designer-writable.interceptor.d.ts +12 -0
  39. package/guards/index.d.ts +1 -0
  40. package/interfaces/definition-bundle.interface.d.ts +111 -0
  41. package/interfaces/entity-builder-module.interface.d.ts +6 -0
  42. package/interfaces/flow-definition.interface.d.ts +13 -9
  43. package/interfaces/generic-record.interface.d.ts +11 -1
  44. package/interfaces/index.d.ts +1 -0
  45. package/package.json +5 -6
  46. package/rule-engine/rule-engine.service.d.ts +3 -1
  47. package/rule-engine/rule-permission.d.ts +3 -7
  48. package/rule-engine/rule-regex.d.ts +0 -2
  49. package/rule-engine/rule-values.d.ts +4 -1
  50. package/rule-engine/rule.interface.d.ts +2 -3
  51. package/services/definition-bundle.diff.d.ts +62 -0
  52. package/services/definition-bundle.file.d.ts +7 -0
  53. package/services/definition-bundle.service.d.ts +32 -0
  54. package/services/entity-builder-config.service.d.ts +2 -0
  55. package/services/entity-flow-scaffold.d.ts +1 -1
  56. package/services/flow-definition.service.d.ts +25 -12
  57. package/services/flow-execution.service.d.ts +7 -0
  58. package/services/flow-executor.service.d.ts +8 -8
  59. package/services/generic-entity.service.d.ts +5 -1
  60. package/services/index.d.ts +3 -1
  61. package/services/schema-evolution.service.d.ts +3 -1
  62. package/services/schema-sync.service.d.ts +5 -1
  63. package/controllers/flow-api-key.controller.d.ts +0 -14
  64. package/entities/flow-api-key.entity.d.ts +0 -10
  65. package/services/flow-api-key.service.d.ts +0 -31
@@ -1,26 +1,79 @@
1
- import * as __rspack_external__flusys_nestjs_shared_exceptions_3edf22e9 from "@flusys/nestjs-shared/exceptions";
1
+ import * as __rspack_external__flusys_nestjs_shared_interfaces_413f2706 from "@flusys/nestjs-shared/interfaces";
2
2
  import * as __rspack_external__flusys_nestjs_shared_modules_24702bee from "@flusys/nestjs-shared/modules";
3
3
  import * as __rspack_external__flusys_nestjs_shared_utils_9125c1f1 from "@flusys/nestjs-shared/utils";
4
4
  import * as __rspack_external__nestjs_common_a04939da from "@nestjs/common";
5
- import * as __rspack_external_node_crypto_2e7c4b46 from "node:crypto";
6
5
  import * as __rspack_external_node_net_5ed819e1 from "node:net";
7
- import * as __rspack_external__flusys_nestjs_shared_interfaces_413f2706 from "@flusys/nestjs-shared/interfaces";
8
- import * as __rspack_external_re2js from "re2js";
9
- export const __rspack_esm_id = 489;
10
- export const __rspack_esm_ids = [489];
6
+ export const __rspack_esm_id = 857;
7
+ export const __rspack_esm_ids = [857];
11
8
  export const __webpack_modules__ = {
12
9
  3372(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
13
10
  const RECORD_FILTER_OPS = [
14
11
  'eq',
15
12
  'ne',
13
+ 'ieq',
16
14
  'gt',
17
15
  'gte',
18
16
  'lt',
19
17
  'lte',
18
+ 'between',
19
+ 'not_between',
20
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',
21
31
  'is_null',
22
32
  'not_null'
23
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
+ }
24
77
  const RECORD_FILTER_LIMITS = {
25
78
  MAX_IN_VALUES: 100
26
79
  };
@@ -39,15 +92,20 @@ const FILTER_CONDITION_KEYS = new Set([
39
92
  }
40
93
 
41
94
  __webpack_require__.d(__webpack_exports__, {
95
+ iA: () => (isFilterRange),
42
96
  t1: () => (isRecordFilterCondition)
43
97
  }, {
44
98
  M5: RECORD_FILTER_LIMITS,
45
- ox: RECORD_FILTER_OPS
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
46
104
  });
47
105
 
48
106
 
49
107
  },
50
- 5920(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
108
+ 8552(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
51
109
 
52
110
  // EXPORTS
53
111
  __webpack_require__.d(__webpack_exports__, {
@@ -64,8 +122,8 @@ __webpack_require__.d(__webpack_exports__, {
64
122
 
65
123
  // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule.interface.ts
66
124
  var rule_interface = __webpack_require__(2354);
67
- ;// CONCATENATED MODULE: external "@flusys/nestjs-shared/interfaces"
68
-
125
+ // EXTERNAL MODULE: external "@flusys/nestjs-shared/interfaces"
126
+ var interfaces_ = __webpack_require__(5103);
69
127
  // EXTERNAL MODULE: external "@flusys/nestjs-shared/modules"
70
128
  var modules_ = __webpack_require__(1236);
71
129
  // EXTERNAL MODULE: external "@flusys/nestjs-shared/utils"
@@ -76,14 +134,87 @@ var common_ = __webpack_require__(6157);
76
134
  var external_node_crypto_ = __webpack_require__(2561);
77
135
  // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/config/message-keys.ts
78
136
  var message_keys = __webpack_require__(5732);
79
- // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/interfaces/generic-record.interface.ts
80
- var generic_record_interface = __webpack_require__(3372);
81
137
  // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-ip.ts
82
138
  var rule_ip = __webpack_require__(809);
83
139
  // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-permission.ts
84
140
  var rule_permission = __webpack_require__(5191);
85
- // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-regex.ts + 1 modules
86
- var rule_regex = __webpack_require__(6308);
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
+
87
218
  // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-values.ts
88
219
  var rule_values = __webpack_require__(6622);
89
220
  ;// CONCATENATED MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-engine.service.ts
@@ -121,7 +252,6 @@ function _ts_param(paramIndex, decorator) {
121
252
 
122
253
 
123
254
 
124
-
125
255
  const FORBIDDEN_PATH_KEYS = new Set([
126
256
  '__proto__',
127
257
  'constructor',
@@ -147,6 +277,12 @@ class RuleEngineService {
147
277
  cache: this.permissionCache
148
278
  });
149
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
+ }
150
286
  async evaluateGroup(group, ctx, depth = 0, budget = {}) {
151
287
  this.assertWithinLimits(group, depth);
152
288
  const evaluate = (node)=>(0,rule_interface/* .isRuleGroup */.GD)(node) ? this.evaluateGroup(node, ctx, depth + 1, budget) : this.evaluateCondition(node, ctx, budget);
@@ -223,9 +359,9 @@ class RuleEngineService {
223
359
  case 'is_false':
224
360
  return actual === false;
225
361
  case 'matches':
226
- return (0,rule_regex/* .matchesPattern */.MT)(actual, expected);
362
+ return matchesPattern(actual, expected);
227
363
  case 'not_matches':
228
- return !(0,rule_regex/* .matchesPattern */.MT)(actual, expected);
364
+ return !matchesPattern(actual, expected);
229
365
  }
230
366
  }
231
367
  async resolveConditionLeft(condition, ctx, budget) {
@@ -267,6 +403,9 @@ class RuleEngineService {
267
403
  return this.resolveLookup(expression, ctx, budget);
268
404
  }
269
405
  }
406
+ /** For HTML the author writes: the values a template fills in are escaped; any other expression is taken as the HTML it resolves to. */ async resolveHtml(expression, ctx) {
407
+ return expression.type === 'template' ? this.resolveTemplate(expression.template, ctx, utils_.escapeHtml) : this.resolveExpression(expression, ctx);
408
+ }
270
409
  async resolveLookup(expression, ctx, budget) {
271
410
  if (!ctx.lookupResolver) {
272
411
  throw new common_.BadRequestException({
@@ -289,17 +428,7 @@ class RuleEngineService {
289
428
  }
290
429
  const filter = {};
291
430
  for (const [key, item] of Object.entries(expression.filter ?? {})){
292
- if ((0,generic_record_interface/* .isRecordFilterCondition */.t1)(item)) {
293
- const value = item.value === undefined ? undefined : await this.resolveExpression(item.value, ctx, budget);
294
- filter[key] = value === undefined ? {
295
- op: item.op
296
- } : {
297
- op: item.op,
298
- value
299
- };
300
- } else {
301
- filter[key] = (0,rule_values/* .equalsOperand */.$b)(await this.resolveExpression(item, ctx, budget));
302
- }
431
+ filter[key] = await (0,rule_values/* .resolveFilterEntry */.vY)(item, (value)=>this.resolveExpression(value, ctx, budget));
303
432
  }
304
433
  const { rows, total } = await ctx.lookupResolver.find(expression.entity, {
305
434
  filter,
@@ -321,7 +450,7 @@ class RuleEngineService {
321
450
  }
322
451
  }
323
452
  }
324
- resolveTemplate(template, ctx) {
453
+ resolveTemplate(template, ctx, format = (text)=>text) {
325
454
  if (template.length > (/* inlined export .RULE_TEMPLATE_MAX_LENGTH */4000)) {
326
455
  throw new common_.BadRequestException({
327
456
  message: `Template is longer than ${(/* inlined export .RULE_TEMPLATE_MAX_LENGTH */4000)} characters.`,
@@ -337,7 +466,7 @@ class RuleEngineService {
337
466
  for (const match of template.matchAll(pattern)){
338
467
  result += template.slice(last, match.index);
339
468
  const value = this.resolveFieldReference(match[1], ctx);
340
- result += value === null || value === undefined ? '' : typeof value === 'object' ? JSON.stringify(value) : String(value);
469
+ result += value === null || value === undefined ? '' : format(typeof value === 'object' ? JSON.stringify(value) : String(value));
341
470
  last = match.index + match[0].length;
342
471
  }
343
472
  return result + template.slice(last);
@@ -468,7 +597,7 @@ class RuleEngineService {
468
597
  return part === undefined ? null : part.trim();
469
598
  }
470
599
  case 'REGEX_EXTRACT':
471
- return (0,rule_regex/* .extractPattern */.Ax)(resolvedArgs[0], resolvedArgs[1], resolvedArgs[2]);
600
+ return extractPattern(resolvedArgs[0], resolvedArgs[1], resolvedArgs[2]);
472
601
  case 'REPLACE':
473
602
  {
474
603
  const [value, search, replacement] = resolvedArgs;
@@ -655,7 +784,7 @@ class RuleEngineService {
655
784
  RuleEngineService = _ts_decorate([
656
785
  (0,common_.Injectable)(),
657
786
  _ts_param(0, (0,common_.Optional)()),
658
- _ts_param(0, (0,common_.Inject)(__rspack_external__flusys_nestjs_shared_interfaces_413f2706.PERMISSION_RESOLVER)),
787
+ _ts_param(0, (0,common_.Inject)(interfaces_.PERMISSION_RESOLVER)),
659
788
  _ts_param(1, (0,common_.Optional)()),
660
789
  _ts_param(1, (0,common_.Inject)(modules_.SharedPermissionCacheService)),
661
790
  _ts_metadata("design:type", Function),
@@ -761,7 +890,7 @@ __webpack_require__.d(__webpack_exports__, {
761
890
 
762
891
  },
763
892
  5191(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
764
- /* import */ var _flusys_nestjs_shared_exceptions__rspack_import_0 = __webpack_require__(2417);
893
+ /* import */ var _flusys_nestjs_shared_utils__rspack_import_0 = __webpack_require__(9216);
765
894
  /* import */ var _nestjs_common__rspack_import_1 = __webpack_require__(6157);
766
895
  /* import */ var _config_message_keys_js__rspack_import_3 = __webpack_require__(5732);
767
896
  /* import */ var _rule_interface_js__rspack_import_2 = __webpack_require__(2354);
@@ -782,7 +911,7 @@ __webpack_require__.d(__webpack_exports__, {
782
911
  const key = branch ?? '';
783
912
  let codes = memo.get(key);
784
913
  if (!codes) {
785
- codes = loadCodes({
914
+ codes = (0,_flusys_nestjs_shared_utils__rspack_import_0.loadPermissionCodes)({
786
915
  userId: user.id,
787
916
  companyId: user.companyId ?? null,
788
917
  branchId: branch
@@ -793,11 +922,6 @@ __webpack_require__.d(__webpack_exports__, {
793
922
  }
794
923
  };
795
924
  }
796
- async function loadCodes(scope, sources) {
797
- if (sources.resolver) return sources.resolver.getPermissionCodes(scope);
798
- if (sources.cache?.isCacheConfigured()) return sources.cache.getPermissions(scope);
799
- throw new _flusys_nestjs_shared_exceptions__rspack_import_0.PermissionSystemUnavailableException();
800
- }
801
925
  /** A list, or text separated by commas / whitespace, as distinct codes. */ function parsePermissionCodes(value) {
802
926
  const raw = Array.isArray(value) ? value : typeof value === 'string' ? value.split(/[\s,]+/) : [];
803
927
  const codes = [
@@ -828,235 +952,10 @@ __webpack_require__.d(__webpack_exports__, {
828
952
  });
829
953
 
830
954
 
831
- },
832
- 6308(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
833
-
834
- // EXPORTS
835
- __webpack_require__.d(__webpack_exports__, {
836
- Ax: () => (/* binding */ extractPattern),
837
- MT: () => (/* binding */ matchesPattern),
838
- _V: () => (/* binding */ rulePatternProblem)
839
- });
840
-
841
- // EXTERNAL MODULE: external "@nestjs/common"
842
- var common_ = __webpack_require__(6157);
843
- ;// CONCATENATED MODULE: external "re2js"
844
-
845
- // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/config/message-keys.ts
846
- var message_keys = __webpack_require__(5732);
847
- // EXTERNAL MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule.interface.ts
848
- var rule_interface = __webpack_require__(2354);
849
- ;// CONCATENATED MODULE: ./projects/nestjs-entity-builder/src/rule-engine/rule-regex.ts
850
-
851
-
852
-
853
-
854
- const MAX_CACHED_PATTERNS = 200;
855
- const compiled = new Map();
856
- const tooComplex = new Map();
857
- function remember(cache, pattern, make) {
858
- if (cache.has(pattern)) return cache.get(pattern);
859
- const value = make(pattern);
860
- if (cache.size >= MAX_CACHED_PATTERNS) cache.delete(cache.keys().next().value);
861
- cache.set(pattern, value);
862
- return value;
863
- }
864
- /** Why a pattern cannot be used, or null when it compiles within the limits. */ function rulePatternProblem(pattern) {
865
- if (pattern.length > rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_PATTERN_LENGTH */.bw.MAX_REGEX_PATTERN_LENGTH) return 'too_long';
866
- if (remember(tooComplex, pattern, isTooComplex)) return 'too_complex';
867
- try {
868
- compile(pattern);
869
- return null;
870
- } catch {
871
- return 'invalid';
872
- }
873
- }
874
- const newFrame = ()=>({
875
- size: 0,
876
- last: 0,
877
- lastProduct: 1,
878
- maxProduct: 1
879
- });
880
- /**
881
- * RE2 unrolls counted repeats (`x{2,50}` becomes 50 copies of x), so match time grows with the
882
- * product of nested counts. Rejects a count above MAX_REGEX_REPEAT, nested counts whose product
883
- * is above it, and a pattern whose unrolled size grows by more than MAX_REGEX_REPEAT_EXPANSION.
884
- * `*`, `+` and `?` do not unroll and stay allowed, nested or not.
885
- */ function isTooComplex(pattern) {
886
- const { MAX_REGEX_REPEAT, MAX_REGEX_REPEAT_EXPANSION } = rule_interface/* .RULE_ENGINE_LIMITS */.bw;
887
- const stack = [
888
- newFrame()
889
- ];
890
- const top = ()=>stack[stack.length - 1];
891
- let atoms = 0;
892
- const atom = (size, product)=>{
893
- const frame = top();
894
- frame.size += size;
895
- frame.last = size;
896
- frame.lastProduct = product;
897
- frame.maxProduct = Math.max(frame.maxProduct, product);
898
- };
899
- let i = 0;
900
- while(i < pattern.length){
901
- const c = pattern[i];
902
- if (c === '\\') {
903
- const next = pattern[i + 1];
904
- i += 2;
905
- if ((next === 'p' || next === 'P' || next === 'x') && pattern[i] === '{') i = closing(pattern, i, '}');
906
- atoms++;
907
- atom(1, 1);
908
- } else if (c === '[') {
909
- i = classEnd(pattern, i);
910
- atoms++;
911
- atom(1, 1);
912
- } else if (c === '(') {
913
- i++;
914
- if (pattern[i] === '?') {
915
- const flagsOnly = /^\?[a-zA-Z-]*\)/.exec(pattern.slice(i));
916
- if (flagsOnly) {
917
- i += flagsOnly[0].length;
918
- continue;
919
- }
920
- const marker = /^\?(?:P?<[^>]*>|[a-zA-Z-]*:)/.exec(pattern.slice(i));
921
- i += marker ? marker[0].length : 1;
922
- }
923
- stack.push(newFrame());
924
- } else if (c === ')') {
925
- i++;
926
- if (stack.length === 1) continue;
927
- const group = stack.pop();
928
- atom(group.size, group.maxProduct);
929
- } else if (c === '|') {
930
- i++;
931
- top().last = 0;
932
- top().lastProduct = 1;
933
- } else if (c === '{') {
934
- const repeat = /^\{(\d+)(,(\d*))?\}\??/.exec(pattern.slice(i));
935
- if (!repeat) {
936
- i++;
937
- atoms++;
938
- atom(1, 1);
939
- continue;
940
- }
941
- i += repeat[0].length;
942
- const min = Number(repeat[1]);
943
- const max = repeat[2] === undefined ? min : repeat[3] ? Number(repeat[3]) : min + 1;
944
- if (min > MAX_REGEX_REPEAT || max > MAX_REGEX_REPEAT) return true;
945
- const frame = top();
946
- const product = frame.lastProduct * Math.max(max, 1);
947
- if (product > MAX_REGEX_REPEAT) return true;
948
- const extra = frame.last * (Math.max(max, 1) - 1);
949
- frame.size += extra;
950
- frame.last += extra;
951
- frame.lastProduct = product;
952
- frame.maxProduct = Math.max(frame.maxProduct, product);
953
- } else {
954
- i++;
955
- if (c !== '*' && c !== '+' && c !== '?') {
956
- atoms++;
957
- atom(1, 1);
958
- }
959
- }
960
- }
961
- while(stack.length > 1){
962
- const group = stack.pop();
963
- atom(group.size, group.maxProduct);
964
- }
965
- return stack[0].size - atoms > MAX_REGEX_REPEAT_EXPANSION;
966
- }
967
- function closing(pattern, from, char) {
968
- const end = pattern.indexOf(char, from);
969
- return end < 0 ? pattern.length : end + 1;
970
- }
971
- function classEnd(pattern, start) {
972
- let j = start + 1;
973
- if (pattern[j] === '^') j++;
974
- if (pattern[j] === ']') j++;
975
- while(j < pattern.length && pattern[j] !== ']'){
976
- if (pattern[j] === '\\') j += 2;
977
- else if (pattern.startsWith('[:', j)) j = closing(pattern, j + 2, ']');
978
- else j++;
979
- }
980
- return j + 1;
981
- }
982
- /** RE2 (linear-time) search: true when the pattern matches anywhere in the input. */ function matchesPattern(input, pattern) {
983
- const prepared = prepare(input, pattern);
984
- return prepared ? prepared.regex.matcher(prepared.text).find() : false;
985
- }
986
- /**
987
- * The first match's capture `group` (default: the first group when the pattern has one, else the
988
- * whole match); null when nothing matches or the group does not exist.
989
- */ function extractPattern(input, pattern, group) {
990
- const prepared = prepare(input, pattern);
991
- if (!prepared) return null;
992
- const index = group === undefined || group === null || group === '' ? prepared.regex.groupCount() > 0 ? 1 : 0 : Number(group);
993
- if (!Number.isInteger(index) || index < 0 || index > prepared.regex.groupCount()) return null;
994
- const matcher = prepared.regex.matcher(prepared.text);
995
- return matcher.find() ? matcher.group(index) ?? null : null;
996
- }
997
- function prepare(input, pattern) {
998
- if (typeof pattern !== 'string') {
999
- throw new common_.BadRequestException({
1000
- message: 'A regular expression pattern must be text.',
1001
- messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INVALID */.x3.REGEX_INVALID,
1002
- messageVariables: {
1003
- pattern: JSON.stringify(pattern ?? null)
1004
- }
1005
- });
1006
- }
1007
- const problem = rulePatternProblem(pattern);
1008
- if (problem) throw patternError(problem, pattern);
1009
- const text = typeof input === 'string' ? input : typeof input === 'number' || typeof input === 'boolean' ? String(input) : null;
1010
- if (text === null) return null;
1011
- if (text.length > rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_INPUT_LENGTH */.bw.MAX_REGEX_INPUT_LENGTH) {
1012
- throw new common_.BadRequestException({
1013
- 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.`,
1014
- messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INPUT_TOO_LONG */.x3.REGEX_INPUT_TOO_LONG,
1015
- messageVariables: {
1016
- max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_INPUT_LENGTH */.bw.MAX_REGEX_INPUT_LENGTH
1017
- }
1018
- });
1019
- }
1020
- return {
1021
- regex: compile(pattern),
1022
- text
1023
- };
1024
- }
1025
- function patternError(problem, pattern) {
1026
- switch(problem){
1027
- case 'too_long':
1028
- return new common_.BadRequestException({
1029
- message: `A regular expression pattern can be at most ${rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_PATTERN_LENGTH */.bw.MAX_REGEX_PATTERN_LENGTH} characters.`,
1030
- messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_PATTERN_TOO_LONG */.x3.REGEX_PATTERN_TOO_LONG,
1031
- messageVariables: {
1032
- max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_PATTERN_LENGTH */.bw.MAX_REGEX_PATTERN_LENGTH
1033
- }
1034
- });
1035
- case 'too_complex':
1036
- return new common_.BadRequestException({
1037
- 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.`,
1038
- messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_TOO_COMPLEX */.x3.REGEX_TOO_COMPLEX,
1039
- messageVariables: {
1040
- max: rule_interface/* .RULE_ENGINE_LIMITS.MAX_REGEX_REPEAT */.bw.MAX_REGEX_REPEAT
1041
- }
1042
- });
1043
- case 'invalid':
1044
- return new common_.BadRequestException({
1045
- message: `'${pattern}' is not a valid regular expression.`,
1046
- messageKey: message_keys/* .RULE_ENGINE_MESSAGES.REGEX_INVALID */.x3.REGEX_INVALID,
1047
- messageVariables: {
1048
- pattern
1049
- }
1050
- });
1051
- }
1052
- }
1053
- function compile(pattern) {
1054
- return remember(compiled, pattern, (p)=>__rspack_external_re2js.RE2JS.compile(p));
1055
- }
1056
-
1057
-
1058
955
  },
1059
956
  6622(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
957
+ /* import */ var _interfaces_generic_record_interface_js__rspack_import_0 = __webpack_require__(3372);
958
+
1060
959
  const ISO_DATE_PREFIX = /^\s*\d{4}-\d{2}-\d{2}/;
1061
960
  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;
1062
961
  const EXPLICIT_ZONE = /(?:\bZ|\bGMT|\bUTC|[+-]\d{2}:?\d{2})$/i;
@@ -1107,27 +1006,62 @@ function instant(value) {
1107
1006
  }
1108
1007
  const includesValue = (list, value)=>list.some((item)=>valuesEqual(item, value));
1109
1008
  /**
1110
- * A resolved filter value is only ever an operand: an object or a list (e.g. `{ "op": "not_null" }`
1111
- * sent as input) is wrapped as the operand of `eq`, which the entity service refuses as not a single
1112
- * value, so it never becomes an operator. Only authored `{ op, value }` entries are operators.
1113
- */ const equalsOperand = (value)=>value !== null && typeof value === 'object' ? {
1009
+ * A filter entry with its expressions resolved, as the entity service takes it: a plain expression
1010
+ * is `eq`, a `range` becomes `[from, to]`. `value` is undefined when a value it needs resolves to
1011
+ * undefined. A resolved value is only ever an operand, so an object or list sent as input (e.g.
1012
+ * `{ "op": "not_null" }`) never becomes an operator: the entity service refuses it as not a value.
1013
+ */ async function resolveFilterEntry(item, resolve) {
1014
+ if (!(0,_interfaces_generic_record_interface_js__rspack_import_0/* .isRecordFilterCondition */.t1)(item)) return {
1114
1015
  op: 'eq',
1115
- value
1116
- } : value;
1016
+ value: await resolve(item)
1017
+ };
1018
+ const { op, value } = item;
1019
+ switch(_interfaces_generic_record_interface_js__rspack_import_0/* .FILTER_OP_VALUE_KIND */.w9[op]){
1020
+ case 'none':
1021
+ return {
1022
+ op
1023
+ };
1024
+ case 'range':
1025
+ {
1026
+ if (!(0,_interfaces_generic_record_interface_js__rspack_import_0/* .isFilterRange */.iA)(value)) return {
1027
+ op,
1028
+ value: undefined
1029
+ };
1030
+ const from = await resolve(value.from);
1031
+ const to = await resolve(value.to);
1032
+ return {
1033
+ op,
1034
+ value: from === undefined || to === undefined ? undefined : [
1035
+ from,
1036
+ to
1037
+ ]
1038
+ };
1039
+ }
1040
+ default:
1041
+ return {
1042
+ op,
1043
+ value: value === undefined ? undefined : await resolve(value)
1044
+ };
1045
+ }
1046
+ }
1047
+ /** 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;
1117
1048
 
1118
1049
  __webpack_require__.d(__webpack_exports__, {
1119
1050
  hz: () => (parseDateText),
1120
- lu: () => (valuesEqual)
1051
+ lu: () => (valuesEqual),
1052
+ vY: () => (resolveFilterEntry)
1121
1053
  }, {
1122
- $b: equalsOperand,
1123
1054
  XL: includesValue,
1124
- YN: ISO_DATE_PREFIX
1055
+ YN: ISO_DATE_PREFIX,
1056
+ kp: isFilterValueMissing
1125
1057
  });
1126
1058
 
1127
1059
 
1128
1060
  },
1129
1061
  2354(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1130
- /** Declarative JSON rule/expression grammar - evaluated by a closed switch, never as code. */ const RULE_COMPARISON_OPERATORS = [
1062
+ /* import */ var _flusys_nestjs_shared_utils__rspack_import_0 = __webpack_require__(9216);
1063
+ /** Declarative JSON rule/expression grammar - evaluated by a closed switch, never as code. */
1064
+ const RULE_COMPARISON_OPERATORS = [
1131
1065
  'equals',
1132
1066
  'not_equals',
1133
1067
  'greater_than',
@@ -1176,12 +1110,11 @@ const RULE_ENGINE_LIMITS = {
1176
1110
  MAX_GROUP_DEPTH: 8,
1177
1111
  MAX_CONDITIONS_PER_GROUP: 100,
1178
1112
  MAX_LOOKUPS: 10,
1179
- MAX_REGEX_PATTERN_LENGTH: 500,
1180
- MAX_REGEX_INPUT_LENGTH: 10_000,
1181
- /** Largest `{n,m}` count, also for the product of nested counts. */ MAX_REGEX_REPEAT: 100,
1182
- /** How much larger counted repeats may make the unrolled pattern than the pattern itself. */ MAX_REGEX_REPEAT_EXPANSION: 300,
1113
+ MAX_REGEX_PATTERN_LENGTH: _flusys_nestjs_shared_utils__rspack_import_0.SAFE_REGEX_LIMITS.MAX_PATTERN_LENGTH,
1114
+ MAX_REGEX_INPUT_LENGTH: _flusys_nestjs_shared_utils__rspack_import_0.SAFE_REGEX_LIMITS.MAX_INPUT_LENGTH,
1115
+ /** 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,
1183
1116
  /** Largest `offsetMinutes` accepted by START_OF_DAY / END_OF_DAY (UTC+14 / UTC-12). */ MAX_UTC_OFFSET_MINUTES: 840,
1184
- MAX_PERMISSION_CODES: 50,
1117
+ MAX_PERMISSION_CODES: _flusys_nestjs_shared_utils__rspack_import_0.MAX_PERMISSION_LOGIC_CODES,
1185
1118
  MAX_IP_RANGES: 100
1186
1119
  };
1187
1120
 
@@ -1198,9 +1131,9 @@ __webpack_require__.d(__webpack_exports__, {
1198
1131
 
1199
1132
 
1200
1133
  },
1201
- 2417(module) {
1134
+ 5103(module) {
1202
1135
 
1203
- module.exports = __rspack_external__flusys_nestjs_shared_exceptions_3edf22e9;
1136
+ module.exports = __rspack_external__flusys_nestjs_shared_interfaces_413f2706;
1204
1137
 
1205
1138
 
1206
1139
  },
@@ -1221,12 +1154,6 @@ module.exports = __rspack_external__flusys_nestjs_shared_utils_9125c1f1;
1221
1154
  module.exports = __rspack_external__nestjs_common_a04939da;
1222
1155
 
1223
1156
 
1224
- },
1225
- 2561(module) {
1226
-
1227
- module.exports = __rspack_external_node_crypto_2e7c4b46;
1228
-
1229
-
1230
1157
  },
1231
1158
  8299(module) {
1232
1159