@flowerforce/flower-core 3.0.1-beta.6 → 3.1.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/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 3.1.0 (2024-06-06)
2
+
3
+
4
+ ### 🚀 Features
5
+
6
+ - add restart action in core ([800da33](https://github.com/flowerforce/flower/commit/800da33))
7
+
8
+ - add devtool to demo - remove duplicated export type ([88117d6](https://github.com/flowerforce/flower/commit/88117d6))
9
+
10
+ - allow custom functions when defining rules and navigation between nodes ([b35f5da](https://github.com/flowerforce/flower/commit/b35f5da))
11
+
12
+
13
+ ### 🩹 Fixes
14
+
15
+ - fix circular dependency on rules matchers ([0bcb02f](https://github.com/flowerforce/flower/commit/0bcb02f))
16
+
17
+ - align packages ([210a284](https://github.com/flowerforce/flower/commit/210a284))
18
+
1
19
  ## 3.0.0 (2024-05-20)
2
20
 
3
21
  This was a version bump only for flower-core to align it with other projects, there were no code changes.
package/dist/index.cjs.js CHANGED
@@ -1,10 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var _get = require('lodash/get');
4
- var isBuffer = require('lodash/isBuffer');
5
3
  var tinyEmitter = require('tiny-emitter');
6
4
  var _set = require('lodash/set');
7
5
  var _unset = require('lodash/unset');
6
+ var _get = require('lodash/get');
8
7
  var _last = require('lodash/last');
9
8
  var _slice = require('lodash/slice');
10
9
  var _cloneDeep = require('lodash/cloneDeep');
@@ -19,106 +18,7 @@ var mapKeys = require('lodash/mapKeys');
19
18
  var mapValues = require('lodash/mapValues');
20
19
  var _trimStart = require('lodash/trimStart');
21
20
  var _intersection = require('lodash/intersection');
22
-
23
- const keyIdentity = key => key;
24
- const flatten = (target, opts) => {
25
- const options = opts ?? {};
26
- const safe = _get(options, 'safe', false);
27
- const maxDepth = _get(options, 'maxDepth', 0);
28
- const delimiter = _get(options, 'delimiter', '.');
29
- const transformKey = _get(options, 'transformKey', keyIdentity);
30
- const output = {};
31
- const step = (object, prev, currentDepth) => {
32
- const depth = currentDepth || 1;
33
- Object.keys(object).forEach(key => {
34
- const value = object[key];
35
- const isarray = safe && Array.isArray(value);
36
- const type = Object.prototype.toString.call(value);
37
- const isbuffer = isBuffer(value);
38
- const isobject = type === '[object Object]' || type === '[object Array]';
39
- const newKey = prev ? prev + delimiter + transformKey(key) : transformKey(key);
40
- if (!isarray && !isbuffer && isobject && Object.keys(value).length && (!maxDepth || depth < maxDepth)) {
41
- return step(value, newKey, depth + 1);
42
- }
43
- output[newKey] = value;
44
- });
45
- };
46
- step(target);
47
- return output;
48
- };
49
- const unflatten = (target, opts) => {
50
- const options = opts ?? {};
51
- const object = _get(options, 'object', false);
52
- const overwrite = _get(options, 'overwrite', false);
53
- const delimiter = _get(options, 'delimiter', '.');
54
- const transformKey = _get(options, 'transformKey', keyIdentity);
55
- const result = {};
56
- const isbuffer = isBuffer(target);
57
- if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') {
58
- return target;
59
- }
60
- const getkey = key => {
61
- const parsedKey = Number(key);
62
- return isNaN(parsedKey) || key?.indexOf('.') !== -1 || object ? key : parsedKey;
63
- };
64
- function addKeys(keyPrefix, recipient, target) {
65
- return Object.keys(target).reduce((result, key) => {
66
- result[keyPrefix + delimiter + key] = target[key];
67
- return result;
68
- }, recipient);
69
- }
70
- function isEmpty(val) {
71
- const type = Object.prototype.toString.call(val);
72
- const isArray = type === '[object Array]';
73
- const isObject = type === '[object Object]';
74
- if (!val) {
75
- return true;
76
- }
77
- if (isArray) {
78
- return !val.length;
79
- }
80
- if (isObject) {
81
- return !Object.keys(val).length;
82
- }
83
- }
84
- target = Object.keys(target).reduce((result, key) => {
85
- const type = Object.prototype.toString.call(target[key]);
86
- const isObject = type === '[object Object]' || type === '[object Array]';
87
- if (!isObject || isEmpty(target[key])) {
88
- result[key] = target[key];
89
- return result;
90
- }
91
- return addKeys(key, result, flatten(target[key], opts));
92
- }, {});
93
- Object.keys(target).forEach(key => {
94
- const split = key.split(delimiter).map(transformKey);
95
- let key1 = getkey(split.shift());
96
- let key2 = getkey(split[0]);
97
- let recipient = result;
98
- while (key2 !== undefined) {
99
- const recipient_key_1 = key1 && _get(recipient, key1);
100
- const type = Object.prototype.toString.call(recipient_key_1);
101
- const isobject = type === '[object Object]' || type === '[object Array]';
102
- if (!overwrite && !isobject && typeof recipient_key_1 !== 'undefined') {
103
- return;
104
- }
105
- if (overwrite && !isobject || !overwrite && recipient_key_1 == null) {
106
- recipient[key1] = typeof key2 === 'number' && !object ? [] : {};
107
- }
108
- recipient = key1 && _get(recipient, key1);
109
- if (split.length > 0) {
110
- key1 = getkey(split.shift());
111
- key2 = getkey(split[0]);
112
- }
113
- }
114
- recipient[key1] = unflatten(target[key], opts);
115
- });
116
- return result;
117
- };
118
- const flat = {
119
- flatten,
120
- unflatten
121
- };
21
+ var flat = require('flat');
122
22
 
123
23
  const Emitter = new tinyEmitter.TinyEmitter();
124
24
 
@@ -291,6 +191,7 @@ const rulesMatcherUtils = {
291
191
  },
292
192
  getKeys: (rules, options) => {
293
193
  if (!rules) return null;
194
+ if (typeof rules == 'function') return [];
294
195
  if (!rulesMatcherUtils.forceArray(rules).every(r => rulesMatcherUtils.isObject(r))) return null;
295
196
  const keys = {};
296
197
  const conditions = Array.isArray(rules) ? {
@@ -320,6 +221,9 @@ const operators = {
320
221
 
321
222
  const rulesMatcher = (rules, formValue = {}, apply = true, options) => {
322
223
  if (!rules) return [apply];
224
+ if (typeof rules === 'function') {
225
+ return [rules(formValue) === apply];
226
+ }
323
227
  const conditions = Array.isArray(rules) ? {
324
228
  $and: rules
325
229
  } : rules;
@@ -448,6 +352,9 @@ const CoreUtils = {
448
352
  if (typeof rule.rules === 'string') {
449
353
  return false;
450
354
  }
355
+ if (typeof rule.rules === 'function') {
356
+ return rule.rules(value);
357
+ }
451
358
  if (rule.rules === null) {
452
359
  return true;
453
360
  }
@@ -909,6 +816,9 @@ const FlowerCoreStateSelectors = {
909
816
  $self: _get(newState, [flowName, ...id.split('.')])
910
817
  } : {});
911
818
  if (!rules) return false;
819
+ if (typeof rules === 'function') {
820
+ return !rules(state);
821
+ }
912
822
  if (!keys) return false;
913
823
  const res = keys.reduce((acc, inc) => {
914
824
  const k = inc;
@@ -970,7 +880,6 @@ exports.RulesOperators = void 0;
970
880
 
971
881
  exports.CoreUtils = CoreUtils;
972
882
  exports.Emitter = Emitter;
973
- exports.Flat = flat;
974
883
  exports.FlowerCoreReducers = FlowerCoreReducers;
975
884
  exports.FlowerStateUtils = FlowerStateUtils;
976
885
  exports.MatchRules = MatchRules;
package/dist/index.esm.js CHANGED
@@ -1,8 +1,7 @@
1
- import _get from 'lodash/get';
2
- import isBuffer from 'lodash/isBuffer';
3
1
  import { TinyEmitter } from 'tiny-emitter';
4
2
  import _set from 'lodash/set';
5
3
  import _unset from 'lodash/unset';
4
+ import _get from 'lodash/get';
6
5
  import _last from 'lodash/last';
7
6
  import _slice from 'lodash/slice';
8
7
  import _cloneDeep from 'lodash/cloneDeep';
@@ -17,106 +16,7 @@ import mapKeys from 'lodash/mapKeys';
17
16
  import mapValues from 'lodash/mapValues';
18
17
  import _trimStart from 'lodash/trimStart';
19
18
  import _intersection from 'lodash/intersection';
20
-
21
- const keyIdentity = key => key;
22
- const flatten = (target, opts) => {
23
- const options = opts ?? {};
24
- const safe = _get(options, 'safe', false);
25
- const maxDepth = _get(options, 'maxDepth', 0);
26
- const delimiter = _get(options, 'delimiter', '.');
27
- const transformKey = _get(options, 'transformKey', keyIdentity);
28
- const output = {};
29
- const step = (object, prev, currentDepth) => {
30
- const depth = currentDepth || 1;
31
- Object.keys(object).forEach(key => {
32
- const value = object[key];
33
- const isarray = safe && Array.isArray(value);
34
- const type = Object.prototype.toString.call(value);
35
- const isbuffer = isBuffer(value);
36
- const isobject = type === '[object Object]' || type === '[object Array]';
37
- const newKey = prev ? prev + delimiter + transformKey(key) : transformKey(key);
38
- if (!isarray && !isbuffer && isobject && Object.keys(value).length && (!maxDepth || depth < maxDepth)) {
39
- return step(value, newKey, depth + 1);
40
- }
41
- output[newKey] = value;
42
- });
43
- };
44
- step(target);
45
- return output;
46
- };
47
- const unflatten = (target, opts) => {
48
- const options = opts ?? {};
49
- const object = _get(options, 'object', false);
50
- const overwrite = _get(options, 'overwrite', false);
51
- const delimiter = _get(options, 'delimiter', '.');
52
- const transformKey = _get(options, 'transformKey', keyIdentity);
53
- const result = {};
54
- const isbuffer = isBuffer(target);
55
- if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') {
56
- return target;
57
- }
58
- const getkey = key => {
59
- const parsedKey = Number(key);
60
- return isNaN(parsedKey) || key?.indexOf('.') !== -1 || object ? key : parsedKey;
61
- };
62
- function addKeys(keyPrefix, recipient, target) {
63
- return Object.keys(target).reduce((result, key) => {
64
- result[keyPrefix + delimiter + key] = target[key];
65
- return result;
66
- }, recipient);
67
- }
68
- function isEmpty(val) {
69
- const type = Object.prototype.toString.call(val);
70
- const isArray = type === '[object Array]';
71
- const isObject = type === '[object Object]';
72
- if (!val) {
73
- return true;
74
- }
75
- if (isArray) {
76
- return !val.length;
77
- }
78
- if (isObject) {
79
- return !Object.keys(val).length;
80
- }
81
- }
82
- target = Object.keys(target).reduce((result, key) => {
83
- const type = Object.prototype.toString.call(target[key]);
84
- const isObject = type === '[object Object]' || type === '[object Array]';
85
- if (!isObject || isEmpty(target[key])) {
86
- result[key] = target[key];
87
- return result;
88
- }
89
- return addKeys(key, result, flatten(target[key], opts));
90
- }, {});
91
- Object.keys(target).forEach(key => {
92
- const split = key.split(delimiter).map(transformKey);
93
- let key1 = getkey(split.shift());
94
- let key2 = getkey(split[0]);
95
- let recipient = result;
96
- while (key2 !== undefined) {
97
- const recipient_key_1 = key1 && _get(recipient, key1);
98
- const type = Object.prototype.toString.call(recipient_key_1);
99
- const isobject = type === '[object Object]' || type === '[object Array]';
100
- if (!overwrite && !isobject && typeof recipient_key_1 !== 'undefined') {
101
- return;
102
- }
103
- if (overwrite && !isobject || !overwrite && recipient_key_1 == null) {
104
- recipient[key1] = typeof key2 === 'number' && !object ? [] : {};
105
- }
106
- recipient = key1 && _get(recipient, key1);
107
- if (split.length > 0) {
108
- key1 = getkey(split.shift());
109
- key2 = getkey(split[0]);
110
- }
111
- }
112
- recipient[key1] = unflatten(target[key], opts);
113
- });
114
- return result;
115
- };
116
- const flat = {
117
- flatten,
118
- unflatten
119
- };
19
+ import { unflatten } from 'flat';
120
20
 
121
21
  const Emitter = new TinyEmitter();
122
22
 
@@ -289,6 +189,7 @@ const rulesMatcherUtils = {
289
189
  },
290
190
  getKeys: (rules, options) => {
291
191
  if (!rules) return null;
192
+ if (typeof rules == 'function') return [];
292
193
  if (!rulesMatcherUtils.forceArray(rules).every(r => rulesMatcherUtils.isObject(r))) return null;
293
194
  const keys = {};
294
195
  const conditions = Array.isArray(rules) ? {
@@ -318,6 +219,9 @@ const operators = {
318
219
 
319
220
  const rulesMatcher = (rules, formValue = {}, apply = true, options) => {
320
221
  if (!rules) return [apply];
222
+ if (typeof rules === 'function') {
223
+ return [rules(formValue) === apply];
224
+ }
321
225
  const conditions = Array.isArray(rules) ? {
322
226
  $and: rules
323
227
  } : rules;
@@ -446,6 +350,9 @@ const CoreUtils = {
446
350
  if (typeof rule.rules === 'string') {
447
351
  return false;
448
352
  }
353
+ if (typeof rule.rules === 'function') {
354
+ return rule.rules(value);
355
+ }
449
356
  if (rule.rules === null) {
450
357
  return true;
451
358
  }
@@ -907,6 +814,9 @@ const FlowerCoreStateSelectors = {
907
814
  $self: _get(newState, [flowName, ...id.split('.')])
908
815
  } : {});
909
816
  if (!rules) return false;
817
+ if (typeof rules === 'function') {
818
+ return !rules(state);
819
+ }
910
820
  if (!keys) return false;
911
821
  const res = keys.reduce((acc, inc) => {
912
822
  const k = inc;
@@ -915,7 +825,7 @@ const FlowerCoreStateSelectors = {
915
825
  });
916
826
  }, {});
917
827
  const [disabled] = MatchRules.rulesMatcher(rules, {
918
- ...flat.unflatten(res)
828
+ ...unflatten(res)
919
829
  }, false, {
920
830
  prefix: flowName
921
831
  });
@@ -966,4 +876,4 @@ var RulesOperators;
966
876
  RulesOperators["$regex"] = "$regex";
967
877
  })(RulesOperators || (RulesOperators = {}));
968
878
 
969
- export { CoreUtils, Emitter, flat as Flat, FlowerCoreReducers, FlowerStateUtils, MatchRules, RulesModes, RulesOperators, FlowerCoreStateSelectors as Selectors };
879
+ export { CoreUtils, Emitter, FlowerCoreReducers, FlowerStateUtils, MatchRules, RulesModes, RulesOperators, FlowerCoreStateSelectors as Selectors };
@@ -1,4 +1,5 @@
1
+ import { FunctionRule } from './interfaces';
1
2
  export declare const MatchRules: {
2
- rulesMatcher: (rules?: Record<string, any> | Record<string, any>[], formValue?: Record<string, any>, apply?: boolean, options?: Record<string, any>) => boolean[];
3
+ rulesMatcher: (rules?: Record<string, any> | Record<string, any>[] | FunctionRule, formValue?: Record<string, any>, apply?: boolean, options?: Record<string, any>) => boolean[];
3
4
  utils: import("./rules-matcher/interface").RulesMatcherUtils;
4
5
  };
@@ -1,4 +1,3 @@
1
- export { flat as Flat } from './Flat';
2
1
  export { Emitter } from './Emitter';
3
2
  export { FlowerCoreReducers } from './FlowerCoreStateFunctions';
4
3
  export { FlowerStateUtils } from './FlowerCoreStateUtils';
@@ -67,6 +67,7 @@ type RulesWithName = {
67
67
  rules: RulesObject<any>;
68
68
  };
69
69
  };
70
+ export type FunctionRule = (data: Record<string, any>) => boolean;
70
71
  export type RulesObject<T> = RulesValuesType<T> | {
71
72
  [K in keyof typeof RulesModes]: Array<RulesOperatorsInArray<RulesValuesType<T>>> | Array<RulesObject<RulesValuesType<T>>>;
72
73
  } | Array<Exclude<RulesOperatorsInArray<RulesValuesType<T>>, undefined>>;
@@ -78,7 +79,7 @@ export type GetPath = (idValue?: string) => {
78
79
  export type AllEqual = (...args: Array<number | string | boolean>[]) => boolean;
79
80
  export type FindValidRule<T = Rules<RulesObject<any>>> = (nextRules: {
80
81
  rules: {
81
- rules: T;
82
+ rules: T | FunctionRule;
82
83
  };
83
84
  }, value: Record<string, any>, prefix?: {
84
85
  prefix: string;
@@ -1,5 +1,5 @@
1
1
  import { RulesObject } from './CoreInterface';
2
- import { Flower, Form, Node } from './Store';
2
+ import { Flower, Form, INode } from './Store';
3
3
  export interface ISelectors {
4
4
  selectGlobal<T extends Record<string, any>>(state: {
5
5
  flower: {
@@ -18,7 +18,7 @@ export interface ISelectors {
18
18
  makeSelectCurrentNodeId<T extends Record<string, any>>(flower: Flower<T>, startNodeId: Flower<T>['startId']): string;
19
19
  makeSelectPrevNodeRetain<T extends Record<string, any>>(nodes: Flower<T>['nodes'], history: Flower<T>['history'], current: Flower<T>['current']): boolean | string | undefined;
20
20
  makeSelectCurrentNodeDisabled<T extends Record<string, any>>(nodes: {
21
- [x: string]: Partial<Node>;
21
+ [x: string]: Partial<INode>;
22
22
  }, current: Flower<T>['current']): boolean;
23
23
  makeSelectNodeErrors<T extends Record<string, any>>(form: Form<T> | undefined): {
24
24
  touched: boolean;
@@ -27,7 +27,7 @@ export interface Flower<T extends Record<string, any>> {
27
27
  current: string;
28
28
  history: string[];
29
29
  nodes: {
30
- [x: string]: Node;
30
+ [x: string]: INode;
31
31
  };
32
32
  nextRules: {
33
33
  [x: string]: RulesByNodeId<T>[];
@@ -37,7 +37,7 @@ export interface Flower<T extends Record<string, any>> {
37
37
  [x: string]: Form<T>;
38
38
  };
39
39
  }
40
- export interface Node {
40
+ export interface INode {
41
41
  nodeId: string;
42
42
  nodeType: string;
43
43
  retain?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flower-core",
3
- "version": "3.0.1-beta.6",
3
+ "version": "3.1.0",
4
4
  "description": "Core functions for flowerJS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,12 +25,14 @@
25
25
  "lodash": ">=4"
26
26
  },
27
27
  "devDependencies": {
28
+ "@types/flat": "^5.0.5",
28
29
  "@types/lodash": "^4.17.1",
29
30
  "jest": "^29.7.0",
30
31
  "ts-jest": "^29.1.2",
31
32
  "typescript": "^5.4.5"
32
33
  },
33
34
  "dependencies": {
35
+ "flat": "5.0.2",
34
36
  "tiny-emitter": "^2.1.0"
35
37
  },
36
38
  "exports": {
@@ -1,5 +0,0 @@
1
- import { Flatten, Unflatten } from './interfaces/FlatInterface';
2
- export declare const flat: {
3
- flatten: Flatten;
4
- unflatten: Unflatten;
5
- };