@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 +18 -0
- package/dist/index.cjs.js +12 -103
- package/dist/index.esm.js +14 -104
- package/dist/src/RulesMatcher.d.ts +2 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/interfaces/CoreInterface.d.ts +2 -1
- package/dist/src/interfaces/SelectorsInterface.d.ts +2 -2
- package/dist/src/interfaces/Store.d.ts +2 -2
- package/package.json +3 -1
- package/dist/src/Flat.d.ts +0 -5
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
|
-
...
|
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,
|
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
|
};
|
package/dist/src/index.d.ts
CHANGED
@@ -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,
|
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<
|
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]:
|
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
|
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.
|
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": {
|