@flowerforce/flower-core 4.0.1-beta.0 → 4.0.1-beta.10

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/dist/index.esm.js CHANGED
@@ -30,7 +30,7 @@ const devtoolState = {};
30
30
  const FlowerStateUtils = {
31
31
  getAllData: (state) => state &&
32
32
  Object.entries(state ?? {}).reduce((acc, [k, v]) => ({ ...acc, [k]: v?.data ?? v }), {}),
33
- selectFlowerFormNode: (name) => (state) => _get(state, name),
33
+ selectFlowerDataNode: (name) => (state) => _get(state, name),
34
34
  makeSelectCurrentNextRules: (name) => (state) => {
35
35
  const nextRules = _get(state, [name, 'nextRules']);
36
36
  const currentNodeId = FlowerStateUtils.makeSelectCurrentNodeId(name)(state);
@@ -42,24 +42,107 @@ const FlowerStateUtils = {
42
42
  return _get(subState, ['current']) || startId;
43
43
  },
44
44
  makeSelectNodeErrors: (name) => (state) => {
45
- const form = FlowerStateUtils.selectFlowerFormNode(name)(state);
46
- return createFormData(form);
45
+ const data = FlowerStateUtils.selectFlowerDataNode(name)(state);
46
+ return generateData(data);
47
47
  }
48
48
  };
49
- const createFormData = (form) => {
50
- const validationErrors = form && form.errors;
49
+ const generateData = (data) => {
50
+ const validationErrors = data && data.errors;
51
51
  const allErrors = Object.values(validationErrors || {});
52
52
  return {
53
- isSubmitted: form?.isSubmitted || false,
54
- isDirty: Object.values(form?.dirty || {}).some(Boolean) || false,
55
- hasFocus: form?.hasFocus,
56
- errors: form?.errors,
57
- customErrors: form?.customErrors,
58
- isValidating: form?.isValidating,
53
+ isSubmitted: data?.isSubmitted || false,
54
+ isDirty: Object.values(data?.dirty || {}).some(Boolean) || false,
55
+ hasFocus: data?.hasFocus,
56
+ errors: data?.errors,
57
+ customErrors: data?.customErrors,
58
+ isValidating: data?.isValidating,
59
59
  isValid: allErrors.flat().length === 0
60
60
  };
61
61
  };
62
62
 
63
+ class AbacEngine {
64
+ constructor(rules = []) {
65
+ // compile string conditions once
66
+ this.rules = (rules || [])
67
+ .map((r) => {
68
+ let conditionFn = undefined;
69
+ if (r.condition) {
70
+ try {
71
+ // NOTE: uses new Function -> ensure rules.json is trusted by the app owner
72
+ conditionFn = new Function('subject', 'resource', 'action', 'environment', `return (${r.condition});`);
73
+ }
74
+ catch (err) {
75
+ console.error('ABAC: failed to compile rule condition', r.id, err);
76
+ }
77
+ }
78
+ return { ...r, conditionFn };
79
+ })
80
+ .sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
81
+ }
82
+ decide(ctx) {
83
+ let anyPermit = false;
84
+ for (const r of this.rules) {
85
+ const matchesAction = Array.isArray(r.action)
86
+ ? r.action.includes(ctx.action)
87
+ : r.action === ctx.action || r.action === '*';
88
+ if (!matchesAction)
89
+ continue;
90
+ let matches = true;
91
+ if (r.conditionFn) {
92
+ try {
93
+ matches = !!r.conditionFn(ctx.subject, ctx.resource, ctx.action, ctx.environment);
94
+ }
95
+ catch (err) {
96
+ matches = false;
97
+ console.error(`ABAC: rule ${r.id} threw while evaluating`, err);
98
+ }
99
+ }
100
+ if (!matches)
101
+ continue;
102
+ if (r.effect === 'Deny') {
103
+ // deny-overrides
104
+ return 'Deny';
105
+ }
106
+ if (r.effect === 'Permit') {
107
+ anyPermit = true;
108
+ }
109
+ }
110
+ return anyPermit ? 'Permit' : 'Deny';
111
+ }
112
+ // utility: checks multiple actions and returns those allowed
113
+ allowedActions(ctxBase, actions) {
114
+ return actions.filter((a) => this.decide({ ...ctxBase, action: a }) === 'Permit');
115
+ }
116
+ }
117
+
118
+ let engine = null;
119
+ let rawRules = null;
120
+ let currentSubject = null;
121
+ function initAbac(rules) {
122
+ engine = new AbacEngine(rules);
123
+ rawRules = rules;
124
+ }
125
+ function getAbacEngine() {
126
+ if (!engine)
127
+ console.warn('ABAC engine non inizializzato');
128
+ return engine;
129
+ }
130
+ function getRawRules() {
131
+ return rawRules;
132
+ }
133
+ function isAbacInitialized() {
134
+ return engine !== null;
135
+ }
136
+ function setSubject(subject) {
137
+ currentSubject = subject;
138
+ }
139
+ function getSubject() {
140
+ return currentSubject;
141
+ }
142
+ function clearSubject() {
143
+ currentSubject = null;
144
+ }
145
+
63
146
  const EMPTY_STRING_REGEXP = /^\s*$/;
64
147
  /**
65
148
  * Defines a utility object named rulesMatcherUtils, which contains various helper functions used for processing rules and data in a rule-matching context.
@@ -83,6 +166,11 @@ const rulesMatcherUtils = {
83
166
  if (!operators[op]) {
84
167
  throw new Error(`Error missing operator:${op}`);
85
168
  }
169
+ if (op === '$can') {
170
+ const subject = getSubject();
171
+ const valid = operators['$can'](subject ?? {}, _get(value, 'action'), _get(value, 'resource'));
172
+ return { valid, name: `${pathWithPrefix}___${name || op}` };
173
+ }
86
174
  const valid = operators[op] && operators[op](valueForKey, valueRef, opt, data);
87
175
  return { valid, name: `${pathWithPrefix}___${name || op}` };
88
176
  },
@@ -240,6 +328,11 @@ const rulesMatcherUtils = {
240
328
  * Defines a set of comparison operators used for matching rules against user input.
241
329
  */
242
330
  const operators = {
331
+ $can: (subject, action, resource) => getAbacEngine()?.decide({
332
+ subject: subject ?? {},
333
+ action,
334
+ resource
335
+ }) === 'Permit',
243
336
  $exists: (a, b) => !rulesMatcherUtils.isEmpty(a) === b,
244
337
  $eq: (a, b) => a === b,
245
338
  $ne: (a, b) => a !== b,
@@ -265,19 +358,19 @@ const operators = {
265
358
  .some((c) => c instanceof RegExp ? c.test(a) : new RegExp(c, opt).test(a))
266
359
  };
267
360
 
268
- const rulesMatcher = (rules, formValue = {}, apply = true, options) => {
361
+ const rulesMatcher = (rules, dataValue = {}, apply = true, options) => {
269
362
  if (!rules)
270
363
  return [apply];
271
364
  // if (typeof rules !== 'object' && !Array.isArray(rules)) {
272
365
  // throw new Error('Rules accept only array or object');
273
366
  // }
274
367
  if (typeof rules === 'function') {
275
- return [rules(formValue) === apply];
368
+ return [rules(dataValue) === apply];
276
369
  }
277
370
  const conditions = Array.isArray(rules)
278
371
  ? { $and: rules }
279
372
  : rules;
280
- const valid = rulesMatcherUtils.checkRule(conditions, formValue, options ?? {});
373
+ const valid = rulesMatcherUtils.checkRule(conditions, dataValue, options ?? {});
281
374
  return [valid === apply];
282
375
  };
283
376
 
@@ -302,9 +395,6 @@ const flattenRules = (ob) => {
302
395
  }
303
396
  return result;
304
397
  };
305
- const getRulesExists = (rules) => {
306
- return Object.keys(rules).length ? FlowUtils.mapEdge(rules) : undefined;
307
- };
308
398
  const FlowUtils = {
309
399
  generateRulesName: (nextRules) => {
310
400
  return nextRules.reduce((acc, inc) => {
@@ -361,23 +451,6 @@ const FlowUtils = {
361
451
  return res;
362
452
  },
363
453
  makeRules: (rules) => Object.entries(rules).reduce((acc2, [k, v]) => [...acc2, { nodeId: k, rules: v }], []),
364
- // TODO: This function is strictly related to React nodes, could make sense to move it in the flower-react folder
365
- generateNodesForFlowerJson: (nodes) => nodes
366
- .filter((e) => !!_get(e, 'props.id'))
367
- .map((e) => {
368
- const rules = FlowUtils.makeRules(e.props.to ?? {});
369
- const nextRules = getRulesExists(rules);
370
- const children = e.props.data?.children;
371
- return {
372
- nodeId: e.props.id,
373
- nodeType: e.type.displayName || e.props.as || 'FlowerNode',
374
- nodeTitle: _get(e.props, 'data.title'),
375
- children,
376
- nextRules,
377
- retain: e.props.retain,
378
- disabled: e.props.disabled
379
- };
380
- }),
381
454
  allEqual: (arr, arr2) => arr.length === arr2.length && arr.every((v) => arr2.includes(v)),
382
455
  findValidRule: (nextRules, value, prefix) => find(nextRules, (rule) => {
383
456
  // fix per evitare di entrare in un nodo senza regole, ma con un name,
@@ -404,7 +477,7 @@ const FlowUtils = {
404
477
  })
405
478
  };
406
479
 
407
- const FormUtils = {
480
+ const DataUtils = {
408
481
  cleanPath: (name, char = '^') => _trimStart(name, char),
409
482
  getPath: (idValue) => {
410
483
  if (!idValue) {
@@ -418,9 +491,9 @@ const FormUtils = {
418
491
  };
419
492
  }
420
493
  if (idValue.indexOf('^') === 0) {
421
- const [formName, ...rest] = FormUtils.cleanPath(idValue).split('.');
494
+ const [rootName, ...rest] = DataUtils.cleanPath(idValue).split('.');
422
495
  return {
423
- formName,
496
+ rootName,
424
497
  path: rest
425
498
  };
426
499
  }
@@ -435,7 +508,7 @@ const FormUtils = {
435
508
  */
436
509
  const CoreUtils = {
437
510
  ...FlowUtils,
438
- ...FormUtils
511
+ ...DataUtils
439
512
  };
440
513
 
441
514
  const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule } = CoreUtils;
@@ -648,7 +721,7 @@ const FlowerCoreBaseReducers = {
648
721
  payload: { name: flowName, node: nextNumberNode }
649
722
  });
650
723
  },
651
- prev: (state, { payload }) => {
724
+ back: (state, { payload }) => {
652
725
  const { name, flowName } = payload;
653
726
  FlowerCoreBaseReducers.historyPop(state, {
654
727
  type: 'historyPop',
@@ -672,75 +745,65 @@ const FlowerCoreBaseReducers = {
672
745
  };
673
746
 
674
747
  const { getPath } = CoreUtils;
675
- /**
676
- * formName => FlowerForm
677
- * initialData => FlowerForm
678
- * fieldName => FlowerField
679
- * fieldValue => FlowerField
680
- * errors => FlowerField
681
- * customErrors => FlowerField
682
- * fieldTouched => FlowerField
683
- * fieldDirty => FlowerField
684
- * fieldHasFocus => FlowerField
685
- */
686
748
  const FlowerCoreDataReducers = {
687
- setFormTouched: (state, { payload }) => {
688
- if (!_get(state, typeof payload === 'string' ? payload : payload.formName)) {
749
+ setFormSubmitted: (state, { payload }) => {
750
+ const rootPath = typeof payload === 'string' ? payload : payload.rootName;
751
+ if (!_get(state, [rootPath])) {
689
752
  return state;
690
753
  }
691
- _set(state, typeof payload === 'string' ? payload : payload.formName, true);
754
+ _set(state, [rootPath, 'isSubmitted'], true);
692
755
  return state;
693
756
  },
694
- formAddCustomErrors: (state, { payload }) => {
695
- _set(state, [payload.formName, 'customErrors', payload.id], payload.errors);
757
+ addCustomDataErrors: (state, { payload }) => {
758
+ _set(state, [payload.rootName, 'customErrors', payload.id], payload.errors);
696
759
  },
697
- formAddErrors: (state, { payload }) => {
698
- _set(state, [payload.formName, 'errors', payload.id], payload.errors);
760
+ addDataErrors: (state, { payload }) => {
761
+ _set(state, [payload.rootName, 'errors', payload.id], payload.errors);
699
762
  },
700
- formRemoveErrors: (state, { payload }) => {
701
- _unset(state, [payload.formName, 'errors', payload.id]);
702
- _unset(state, [payload.formName, 'customErrors', payload.id]);
703
- _unset(state, [payload.formName, 'isValidating']);
763
+ removeDataErrors: (state, { payload }) => {
764
+ _unset(state, [payload.rootName, 'errors', payload.id]);
765
+ _unset(state, [payload.rootName, 'customErrors', payload.id]);
766
+ _unset(state, [payload.rootName, 'isValidating']);
704
767
  },
705
- formFieldTouch: (state, { payload }) => {
706
- _set(state, [payload.formName, 'touches', payload.id], payload.touched);
768
+ fieldTouch: (state, { payload }) => {
769
+ _set(state, [payload.rootName, 'touches', payload.id], payload.touched);
707
770
  },
708
- formFieldDirty: (state, { payload }) => {
709
- _set(state, [payload.formName, 'dirty', payload.id], payload.dirty);
771
+ fieldDirty: (state, { payload }) => {
772
+ _set(state, [payload.rootName, 'dirty', payload.id], payload.dirty);
710
773
  },
711
- formFieldFocus: (state, { payload }) => {
774
+ fieldFocus: (state, { payload }) => {
712
775
  if (!payload.focused) {
713
- _unset(state, [payload.formName, 'hasFocus']);
776
+ _unset(state, [payload.rootName, 'hasFocus']);
714
777
  return;
715
778
  }
716
- _set(state, [payload.formName, 'hasFocus'], payload.id);
779
+ _set(state, [payload.rootName, 'hasFocus'], payload.id);
717
780
  },
718
781
  addData: (state, { payload }) => {
719
- const prevData = _get(state, [payload.formName, 'data'], {});
720
- _set(state, [payload.formName, 'data'], { ...prevData, ...payload.value });
782
+ const prevData = _get(state, [payload.rootName, 'data'], {});
783
+ _set(state, [payload.rootName, 'data'], { ...prevData, ...payload.value });
721
784
  },
722
785
  addDataByPath: (state, { payload }) => {
723
786
  const { path: newpath } = getPath(payload.id);
724
787
  if (payload.id && payload.id.length) {
725
- _set(state, [payload.formName, 'data', ...newpath], payload.value);
788
+ _set(state, [payload.rootName, 'data', ...newpath], payload.value);
726
789
  if (payload && payload.dirty) {
727
- _set(state, [payload.formName, 'dirty', payload.id], payload.dirty);
790
+ _set(state, [payload.rootName, 'dirty', payload.id], payload.dirty);
728
791
  }
729
792
  }
730
793
  },
731
794
  // TODO usato al momento solo il devtool
732
795
  replaceData: /* istanbul ignore next */ (state, { payload }) => {
733
796
  /* istanbul ignore next */
734
- _set(state, [payload.formName, 'data'], payload.value);
797
+ _set(state, [payload.rootName, 'data'], payload.value);
735
798
  },
736
799
  unsetData: (state, { payload }) => {
737
- _unset(state, [payload.formName, 'data', ...payload.id]);
800
+ _unset(state, [payload.rootName, 'data', ...payload.id]);
738
801
  },
739
- setFormIsValidating: (state, { payload }) => {
740
- _set(state, [payload.formName, 'isValidating'], payload.isValidating);
802
+ setIsDataValidating: (state, { payload }) => {
803
+ _set(state, [payload.rootName, 'isValidating'], payload.isValidating);
741
804
  },
742
- resetForm: (state, { payload: { formName, initialData } }) => {
743
- const touchedFields = _get(state, [formName, 'errors'], {});
805
+ resetData: (state, { payload: { rootName, initialData } }) => {
806
+ const touchedFields = _get(state, [rootName, 'errors'], {});
744
807
  const newStateData = initialData
745
808
  ? Object.keys(touchedFields).reduce((acc, key) => {
746
809
  const { path } = getPath(key);
@@ -749,13 +812,13 @@ const FlowerCoreDataReducers = {
749
812
  return acc;
750
813
  }, {})
751
814
  : {};
752
- _set(state, [formName, 'data'], newStateData);
753
- _unset(state, [formName, 'touches']);
754
- _unset(state, [formName, 'dirty']);
755
- _unset(state, [formName, 'isSubmitted']);
815
+ _set(state, [rootName, 'data'], newStateData);
816
+ _unset(state, [rootName, 'touches']);
817
+ _unset(state, [rootName, 'dirty']);
818
+ _unset(state, [rootName, 'isSubmitted']);
756
819
  },
757
- initForm: (state, { payload: { formName, initialData } }) => {
758
- _set(state, [formName, 'data'], initialData);
820
+ initData: (state, { payload: { rootName, initialData } }) => {
821
+ _set(state, [rootName, 'data'], initialData);
759
822
  }
760
823
  };
761
824
 
@@ -764,8 +827,6 @@ const FlowerCoreReducers = { ...FlowerCoreBaseReducers, ...FlowerCoreDataReducer
764
827
  const FlowerCoreStateBaseSelectors = {
765
828
  selectGlobal: (state) => state && state[REDUCER_NAME.FLOWER_FLOW],
766
829
  selectFlower: (name) => (state) => _get(state, [name]),
767
- // selectFlowerFormNode: (id) => (state) =>
768
- // _get(state, [REDUCER_NAME.FLOWER_DATA, id]),
769
830
  selectFlowerHistory: (flower) => _get(flower, ['history'], []),
770
831
  makeSelectNodesIds: (flower) => _get(flower, ['nodes']),
771
832
  makeSelectStartNodeId: (flower) => _get(flower, ['startId']),
@@ -794,24 +855,24 @@ const FlowerCoreStateBaseSelectors = {
794
855
 
795
856
  const FlowerCoreStateDataSelectors = {
796
857
  selectGlobalReducerByName: (name) => (state) => state[name] ?? state[REDUCER_NAME.FLOWER_DATA][name],
797
- selectGlobalForm: (state) => {
858
+ selectGlobalData: (state) => {
798
859
  return state && state[REDUCER_NAME.FLOWER_DATA];
799
860
  },
800
861
  // getDataByFlow: (flower) => _get(flower, 'data') ?? {},
801
862
  getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
802
- makeSelectNodeFormSubmitted: (form) => form && form.isSubmitted,
803
- makeSelectNodeFormFieldTouched: (id) => (form) => form && form.touches && form.touches[id],
804
- makeSelectNodeFormFieldFocused: (id) => (form) => {
805
- return form && form.hasFocus === id ? id : undefined;
806
- },
807
- makeSelectNodeFormFieldDirty: (id) => (form) => form && form.dirty && form.dirty[id],
808
- makeSelectNodeErrors: createFormData,
809
- makeSelectFieldError: (name, id, validate) => (data, form) => {
810
- const customErrors = Object.entries((form && form.customErrors) || {})
863
+ makeSelectNodeDataSubmitted: (data) => data && data.isSubmitted,
864
+ makeSelectNodeDataFieldTouched: (id) => (data) => data && data.touches && data.touches[id],
865
+ makeSelectNodeDataFieldFocused: (id) => (data) => {
866
+ return data && data.hasFocus === id ? id : undefined;
867
+ },
868
+ makeSelectNodeDataFieldDirty: (id) => (data) => data && data.dirty && data.dirty[id],
869
+ makeSelectNodeErrors: generateData,
870
+ makeSelectFieldError: (name, id, validate) => (globalData, data) => {
871
+ const customErrors = Object.entries((data && data.customErrors) || {})
811
872
  .filter(([k]) => k === id)
812
873
  .map(([, v]) => v)
813
874
  .flat();
814
- if (!validate || !data)
875
+ if (!validate || !globalData)
815
876
  return [];
816
877
  const errors = validate.filter((rule) => {
817
878
  if (!rule)
@@ -819,7 +880,7 @@ const FlowerCoreStateDataSelectors = {
819
880
  if (!rule.rules)
820
881
  return true;
821
882
  const transformSelf = CoreUtils.mapKeysDeepLodash(rule.rules, (v, key) => key === '$self' ? id : key);
822
- const [hasError] = rulesMatcher(transformSelf, data, false, {
883
+ const [hasError] = rulesMatcher(transformSelf, globalData, false, {
823
884
  prefix: name
824
885
  });
825
886
  return hasError;
@@ -827,8 +888,8 @@ const FlowerCoreStateDataSelectors = {
827
888
  const result = errors.map((r) => (r && r.message) || 'error');
828
889
  return [...customErrors, ...(result.length === 0 ? [] : result)];
829
890
  },
830
- selectorRulesDisabled: (id, rules, keys, flowName, value) => (data, form) => {
831
- const newState = { ...data, ...value, $form: form };
891
+ selectorRulesDisabled: (id, rules, keys, flowName, value) => (globalData, data) => {
892
+ const newState = { ...globalData, ...value, $data: data, $form: data };
832
893
  const state = Object.assign(newState, id ? { $self: _get(newState, [flowName, ...id.split('.')]) } : {});
833
894
  if (!rules)
834
895
  return false;
@@ -853,4 +914,4 @@ const FlowerCoreStateSelectors = {
853
914
  ...FlowerCoreStateDataSelectors
854
915
  };
855
916
 
856
- export { CoreUtils, Emitter, FlowUtils, FlowerCoreBaseReducers, FlowerCoreDataReducers, FlowerCoreReducers, FlowerCoreStateBaseSelectors, FlowerCoreStateDataSelectors, FlowerCoreStateSelectors, FlowerStateUtils, FormUtils, REDUCER_NAME, createFormData, devtoolState, flattenRules, rulesMatcher, rulesMatcherUtils };
917
+ export { AbacEngine, CoreUtils, DataUtils, Emitter, FlowUtils, FlowerCoreBaseReducers, FlowerCoreDataReducers, FlowerCoreReducers, FlowerCoreStateBaseSelectors, FlowerCoreStateDataSelectors, FlowerCoreStateSelectors, FlowerStateUtils, REDUCER_NAME, clearSubject, devtoolState, flattenRules, generateData, getAbacEngine, getRawRules, getSubject, initAbac, isAbacInitialized, rulesMatcher, rulesMatcherUtils, setSubject };
@@ -0,0 +1,32 @@
1
+ export type Action = string;
2
+ export type Subject = Record<string, any>;
3
+ export type Resource = Record<string, any>;
4
+ export type Environment = Record<string, any>;
5
+ export type AbacCtx = {
6
+ subject: Subject;
7
+ resource?: Resource;
8
+ action: Action;
9
+ environment?: Environment;
10
+ };
11
+ export type RuleInput = {
12
+ id: string;
13
+ description?: string;
14
+ effect: 'Permit' | 'Deny';
15
+ priority?: number;
16
+ action?: string | string[];
17
+ /**
18
+ * condition: string JS expression that returns boolean.
19
+ * It can reference `subject`, `resource`, `action`, `environment`.
20
+ * Example: "action === 'read' && (!resource.confidential || resource.ownerID === subject.id)"
21
+ */
22
+ condition?: string;
23
+ };
24
+ export type CompiledRule = RuleInput & {
25
+ conditionFn?: (subject: Subject, resource?: Resource, action?: Action, environment?: Environment) => boolean;
26
+ };
27
+ export declare class AbacEngine {
28
+ private rules;
29
+ constructor(rules?: RuleInput[]);
30
+ decide(ctx: AbacCtx): 'Permit' | 'Deny';
31
+ allowedActions(ctxBase: Omit<AbacCtx, 'action'>, actions: Action[]): string[];
32
+ }
@@ -0,0 +1,8 @@
1
+ import { AbacEngine, RuleInput, Subject } from './abacEngine';
2
+ export declare function initAbac(rules: RuleInput[]): void;
3
+ export declare function getAbacEngine(): AbacEngine | null;
4
+ export declare function getRawRules(): RuleInput[] | null;
5
+ export declare function isAbacInitialized(): boolean;
6
+ export declare function setSubject(subject: Subject): void;
7
+ export declare function getSubject(): Subject | null;
8
+ export declare function clearSubject(): void;
@@ -0,0 +1,2 @@
1
+ export * from './abacEngine';
2
+ export * from './abacSingleton';
@@ -3,4 +3,5 @@ export * from './constants';
3
3
  export * from './utils';
4
4
  export * from './rules-matcher';
5
5
  export * from './state-manager';
6
+ export * from './ABAC';
6
7
  export type * from './interfaces';
@@ -1,5 +1,6 @@
1
1
  export declare enum RulesOperators {
2
2
  $exists = "$exists",
3
+ $can = "$can",
3
4
  $eq = "$eq",
4
5
  $ne = "$ne",
5
6
  $gt = "$gt",
@@ -26,6 +27,15 @@ export type Edge<T = object> = {
26
27
  rules: RulesObject<T>;
27
28
  };
28
29
  };
30
+ export type NodeConfig = {
31
+ nodeId: string | undefined;
32
+ nodeType: string;
33
+ nodeTitle: string;
34
+ children: Node['children'];
35
+ nextRules: ReturnType<MapEdge> | undefined;
36
+ retain: boolean;
37
+ disabled: boolean;
38
+ };
29
39
  export type Node = {
30
40
  nodeId: string | undefined;
31
41
  nodeType: string;
@@ -76,7 +86,7 @@ export type RulesObject<T> = RulesValuesType<T> | {
76
86
  export type CleanPath = (name: string, char?: string) => string;
77
87
  export type GetPath = (idValue?: string) => {
78
88
  path: string | string[];
79
- formName?: string;
89
+ rootName?: string;
80
90
  };
81
91
  export type AllEqual = (...args: Array<number | string | boolean>[]) => boolean;
82
92
  export type FindValidRule<T = Rules<RulesObject<any>>> = (nextRules: {
@@ -93,22 +103,12 @@ export type MapEdge<K = RulesByNodeId<any>, T = K[]> = (nextNode: T) => Array<K>
93
103
  export type MakeRules<T extends Record<string, any> = {
94
104
  rules: RulesObject<any> | object;
95
105
  }> = (rules: T) => Array<RulesByNodeId<T>>;
96
- export type GetRulesExists = (rules: RulesByNodeId<any>[]) => ReturnType<MapEdge> | undefined;
97
- export type GenerateNodesForFlowerJson = (nodes: Node[], edges?: Edge[]) => {
98
- nodeId: string | undefined;
99
- nodeType: string;
100
- nodeTitle: string;
101
- children: Node['children'];
102
- nextRules: ReturnType<GetRulesExists>;
103
- retain: boolean;
104
- disabled: boolean;
105
- }[];
106
106
  export type HasNode = (state: Record<string, any>, name: string, node: string) => boolean;
107
- export type MakeObjectRules = (nodes: Node[]) => {
107
+ export type MakeObjectRules = (nodes: NodeConfig[]) => {
108
108
  [x: string]: Node['nextRules'];
109
109
  };
110
- export type GenerateNodes = (nodes: Node[]) => {
111
- [x: string]: Omit<Node, 'nextRules'>;
110
+ export type GenerateNodes = (nodes: NodeConfig[]) => {
111
+ [x: string]: Partial<Node>;
112
112
  };
113
113
  export type MapKeysDeepLodash = (obj: Record<string, any>, cb: (...args: any) => any, isRecursive?: boolean) => Record<string, any>;
114
114
  export type GenerateRulesName = (nextRules: RulesWithName[]) => {
@@ -176,13 +176,6 @@ export interface FlowUtilitiesFunctions {
176
176
  * @returns
177
177
  */
178
178
  makeRules: MakeRules;
179
- /**
180
- * Generates nodes for a flower JSON structure, extracting rules and other properties.
181
- * @param nodes
182
- *
183
- * @returns
184
- */
185
- generateNodesForFlowerJson: GenerateNodesForFlowerJson;
186
179
  /**
187
180
  * Checks if two arrays are equal in length and have the same elements.
188
181
  * @param arr
@@ -201,7 +194,7 @@ export interface FlowUtilitiesFunctions {
201
194
  */
202
195
  findValidRule: FindValidRule;
203
196
  }
204
- export interface FormUtilitiesFunctions {
197
+ export interface DataUtilitiesFunctions {
205
198
  /**
206
199
  * Removes specified characters from the beginning of a string (default char -> '^').
207
200
  * @param name
@@ -218,6 +211,6 @@ export interface FormUtilitiesFunctions {
218
211
  */
219
212
  getPath: GetPath;
220
213
  }
221
- export interface CoreUtilitiesFunctions extends FormUtilitiesFunctions, FlowUtilitiesFunctions {
214
+ export interface CoreUtilitiesFunctions extends DataUtilitiesFunctions, FlowUtilitiesFunctions {
222
215
  }
223
216
  export {};