@react-typed-forms/schemas 14.0.3 → 14.0.4
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/coverage/clover.xml +679 -0
- package/coverage/coverage-final.json +5 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +131 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/src/controlDefinition.ts.html +2362 -0
- package/coverage/lcov-report/src/index.html +146 -0
- package/coverage/lcov-report/src/schemaField.ts.html +1732 -0
- package/coverage/lcov-report/src/util.ts.html +2821 -0
- package/coverage/lcov-report/test/gen.ts.html +610 -0
- package/coverage/lcov-report/test/index.html +116 -0
- package/coverage/lcov.info +1446 -0
- package/jest.config.js +7 -0
- package/lib/controlBuilder.d.ts +4 -1
- package/lib/controlDefinition.d.ts +13 -0
- package/lib/index.cjs +1 -1
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/schemaField.d.ts +4 -3
- package/lib/util.d.ts +2 -1
- package/package.json +8 -2
- package/test/diff.test.ts +166 -0
- package/test/gen.ts +175 -0
- package/test/play.ts +50 -0
package/lib/schemaField.d.ts
CHANGED
|
@@ -212,7 +212,7 @@ export interface SchemaDataNode {
|
|
|
212
212
|
id: string;
|
|
213
213
|
schema: SchemaNode;
|
|
214
214
|
elementIndex?: number;
|
|
215
|
-
control
|
|
215
|
+
control: Control<any>;
|
|
216
216
|
parent?: SchemaDataNode;
|
|
217
217
|
getChild(schemaNode: SchemaNode): SchemaDataNode;
|
|
218
218
|
getChildElement(index: number): SchemaDataNode;
|
|
@@ -221,7 +221,7 @@ export declare function findField(fields: SchemaField[], field: string): SchemaF
|
|
|
221
221
|
export declare function isScalarField(sf: SchemaField): sf is SchemaField;
|
|
222
222
|
export declare function isCompoundField(sf: SchemaField): sf is CompoundField;
|
|
223
223
|
export declare function createSchemaLookup<A extends Record<string, SchemaField[]>>(schemaMap: A): SchemaTreeLookup<keyof A>;
|
|
224
|
-
export declare function makeSchemaDataNode(schema: SchemaNode, control
|
|
224
|
+
export declare function makeSchemaDataNode(schema: SchemaNode, control: Control<unknown>, parent?: SchemaDataNode, elementIndex?: number): SchemaDataNode;
|
|
225
225
|
export declare function schemaDataForFieldRef(fieldRef: string | undefined, schema: SchemaDataNode): SchemaDataNode;
|
|
226
226
|
export declare function schemaForFieldRef(fieldRef: string | undefined, schema: SchemaNode): SchemaNode;
|
|
227
227
|
export declare function traverseSchemaPath<A>(fieldPath: string[], schema: SchemaNode, acc: A, next: (acc: A, node: SchemaNode) => A): A;
|
|
@@ -243,7 +243,8 @@ export declare enum SchemaTags {
|
|
|
243
243
|
NoControl = "_NoControl",
|
|
244
244
|
HtmlEditor = "_HtmlEditor",
|
|
245
245
|
ControlGroup = "_ControlGroup:",
|
|
246
|
-
ControlRef = "_ControlRef:"
|
|
246
|
+
ControlRef = "_ControlRef:",
|
|
247
|
+
IdField = "_IdField:"
|
|
247
248
|
}
|
|
248
249
|
export declare function getTagParam(field: SchemaField, tag: string): string | undefined;
|
|
249
250
|
export declare function makeParamTag(tag: string, value: string): string;
|
package/lib/util.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ControlActionHandler, ControlDefinition, DataControlDefinition, DisplayOnlyRenderOptions, GroupRenderOptions } from "./controlDefinition";
|
|
2
2
|
import { MutableRefObject } from "react";
|
|
3
|
-
import { CompoundField, FieldOption, SchemaField, SchemaNode } from "./schemaField";
|
|
3
|
+
import { CompoundField, FieldOption, SchemaDataNode, SchemaField, SchemaNode } from "./schemaField";
|
|
4
4
|
/**
|
|
5
5
|
* Interface representing the classes for a control.
|
|
6
6
|
*/
|
|
@@ -243,3 +243,4 @@ export declare function isControlDisplayOnly(def: ControlDefinition): boolean;
|
|
|
243
243
|
* @returns {ControlActionHandler} - The combined action handler.
|
|
244
244
|
*/
|
|
245
245
|
export declare function actionHandlers(...handlers: (ControlActionHandler | undefined)[]): ControlActionHandler;
|
|
246
|
+
export declare function getDiffObject(dataNode: SchemaDataNode, idField?: string | null): any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-typed-forms/schemas",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.cjs",
|
|
@@ -42,6 +42,11 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"react": "^18.2.0",
|
|
44
44
|
"@react-typed-forms/transform": "^0.2.0",
|
|
45
|
+
"jest": "^29.7.0",
|
|
46
|
+
"tsx": "^4.19.1",
|
|
47
|
+
"fast-check": "^3.22.0",
|
|
48
|
+
"ts-jest": "^29.2.5",
|
|
49
|
+
"@jest/globals": "^29.7.0",
|
|
45
50
|
"typedoc": "^0.27.2",
|
|
46
51
|
"@types/uuid": "^10.0.0",
|
|
47
52
|
"@types/react": "^18.2.28",
|
|
@@ -51,12 +56,13 @@
|
|
|
51
56
|
"prettier": "^3.0.3",
|
|
52
57
|
"rimraf": "^3.0.2",
|
|
53
58
|
"typescript": "^5.6.2",
|
|
54
|
-
"@react-typed-forms/core": "4.0.
|
|
59
|
+
"@react-typed-forms/core": "4.0.3"
|
|
55
60
|
},
|
|
56
61
|
"gitHead": "698e16cd3ab31b7dd0528fc76536f4d3205ce8c6",
|
|
57
62
|
"scripts": {
|
|
58
63
|
"build": "rimraf ./lib/ node_modules/.cache && microbundle -f modern,cjs --jsx React.createElement --jsxFragment React.Fragment",
|
|
59
64
|
"watch": "microbundle -w -f modern,cjs --no-compress --jsx React.createElement --jsxFragment React.Fragment",
|
|
65
|
+
"test": "jest --coverage",
|
|
60
66
|
"update-readme": "md-magic --path README.md",
|
|
61
67
|
"gencode": "nswag swagger2tsclient /input:http://localhost:5216/swagger/v1/swagger.json /runtime:Net60 /output:src/types.ts /GenerateClientClasses:false /MarkOptionalProperties:false /Template:Fetch /TypeStyle:Interface /DateTimeType:string"
|
|
62
68
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals";
|
|
2
|
+
import fc from "fast-check";
|
|
3
|
+
import { changeValue, makeDataNode, valueAndSchema } from "./gen";
|
|
4
|
+
import {
|
|
5
|
+
getDiffObject,
|
|
6
|
+
getTagParam,
|
|
7
|
+
isCompoundNode,
|
|
8
|
+
SchemaDataNode,
|
|
9
|
+
SchemaTags,
|
|
10
|
+
} from "../src";
|
|
11
|
+
import { Control } from "@react-typed-forms/core";
|
|
12
|
+
|
|
13
|
+
describe("diff", () => {
|
|
14
|
+
it("unchanged value always returns undefined", () => {
|
|
15
|
+
fc.assert(
|
|
16
|
+
fc.property(valueAndSchema(), (fv) => {
|
|
17
|
+
const dataNode = makeDataNode(fv);
|
|
18
|
+
expect(getDiffObject(dataNode)).toBeUndefined();
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("primitive value always returns new value", () => {
|
|
24
|
+
fc.assert(
|
|
25
|
+
fc.property(
|
|
26
|
+
valueAndSchema({ arrayChance: 0, compoundChance: 0 }),
|
|
27
|
+
(fv) => {
|
|
28
|
+
const dataNode = makeDataNode(fv);
|
|
29
|
+
const control = dataNode.control!;
|
|
30
|
+
control.setValue((x) => changeValue(x, dataNode.schema.field));
|
|
31
|
+
expect(getDiffObject(dataNode)).toBe(control.value);
|
|
32
|
+
},
|
|
33
|
+
),
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("compound fields only return changed values", () => {
|
|
38
|
+
fc.assert(
|
|
39
|
+
fc.property(
|
|
40
|
+
valueAndSchema({ arrayChance: 0, forceCompound: true }),
|
|
41
|
+
(fv) => {
|
|
42
|
+
const dataNode = makeDataNode(fv);
|
|
43
|
+
const control = dataNode.control!;
|
|
44
|
+
const result = { ...control.value };
|
|
45
|
+
const newValue = { ...control.value };
|
|
46
|
+
dataNode.schema.getChildNodes().forEach((child, i) => {
|
|
47
|
+
const field = child.field;
|
|
48
|
+
const fieldName = field.field;
|
|
49
|
+
if (i % 2 == 0) {
|
|
50
|
+
const nv = changeValue(newValue[fieldName], field);
|
|
51
|
+
newValue[fieldName] = nv;
|
|
52
|
+
result[fieldName] = nv;
|
|
53
|
+
} else {
|
|
54
|
+
delete result[fieldName];
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
control.value = newValue;
|
|
58
|
+
expect(getDiffObject(dataNode)).toStrictEqual(result);
|
|
59
|
+
},
|
|
60
|
+
),
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("array compound with id field always returns id field and changes", () => {
|
|
65
|
+
fc.assert(
|
|
66
|
+
fc.property(
|
|
67
|
+
valueAndSchema({
|
|
68
|
+
forceArray: true,
|
|
69
|
+
forceCompound: true,
|
|
70
|
+
arrayChance: 0,
|
|
71
|
+
compoundChance: 0,
|
|
72
|
+
idField: true,
|
|
73
|
+
}),
|
|
74
|
+
(fv) => {
|
|
75
|
+
const dataNode = makeDataNode(fv);
|
|
76
|
+
const arrayControl = dataNode.control!;
|
|
77
|
+
let results: any = undefined;
|
|
78
|
+
arrayControl.as<any[]>().elements.forEach((control) => {
|
|
79
|
+
const { newValue, result } = editCompound(control.value, dataNode);
|
|
80
|
+
control.value = newValue;
|
|
81
|
+
if (!results) results = [];
|
|
82
|
+
results.push(result);
|
|
83
|
+
});
|
|
84
|
+
expect(getDiffObject(dataNode)).toStrictEqual(results);
|
|
85
|
+
},
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("array without id always returns array index edit format", () => {
|
|
91
|
+
fc.assert(
|
|
92
|
+
fc.property(
|
|
93
|
+
valueAndSchema({
|
|
94
|
+
forceArray: true,
|
|
95
|
+
forceCompound: true,
|
|
96
|
+
arrayChance: 0,
|
|
97
|
+
compoundChance: 0,
|
|
98
|
+
}).chain((fv) => {
|
|
99
|
+
const len = ((fv.value as any[]) ?? []).length;
|
|
100
|
+
return fc
|
|
101
|
+
.record({
|
|
102
|
+
index: fc.integer({ min: 0, max: len }),
|
|
103
|
+
add: len ? fc.boolean() : fc.constant(true),
|
|
104
|
+
})
|
|
105
|
+
.map((x) => ({ ...fv, ...x }));
|
|
106
|
+
}),
|
|
107
|
+
(fv) => {
|
|
108
|
+
const dataNode = makeDataNode(fv);
|
|
109
|
+
const arrayControl = dataNode.control!.as<any[]>();
|
|
110
|
+
let results: any = undefined;
|
|
111
|
+
// if (fv.add || fv.index >= arrayControl.elements.length)
|
|
112
|
+
// addElement(
|
|
113
|
+
// arrayControl,
|
|
114
|
+
// changeValue(undefined, dataNode.schema.field, true),
|
|
115
|
+
// );
|
|
116
|
+
arrayControl.as<any[]>().elements.forEach((control, i) => {
|
|
117
|
+
let change = undefined;
|
|
118
|
+
if (i % 2 == 0) {
|
|
119
|
+
if (isCompoundNode(dataNode.schema)) {
|
|
120
|
+
const { newValue, result } = editCompound(
|
|
121
|
+
control.value,
|
|
122
|
+
dataNode,
|
|
123
|
+
);
|
|
124
|
+
control.value = newValue;
|
|
125
|
+
change = result;
|
|
126
|
+
} else {
|
|
127
|
+
change = changeValue(control.value, dataNode.schema.field);
|
|
128
|
+
control.value = change;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (!results) results = [];
|
|
132
|
+
results.push({
|
|
133
|
+
old: i,
|
|
134
|
+
edit: change,
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
expect(getDiffObject(dataNode)).toStrictEqual(results);
|
|
138
|
+
},
|
|
139
|
+
),
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
function editCompound(
|
|
145
|
+
existing: Record<string, any>,
|
|
146
|
+
dataNode: SchemaDataNode,
|
|
147
|
+
): { newValue: any; result: any } {
|
|
148
|
+
const idField = getTagParam(dataNode.schema.field, SchemaTags.IdField);
|
|
149
|
+
const result = { ...existing };
|
|
150
|
+
const newValue = { ...existing };
|
|
151
|
+
dataNode.schema.getChildNodes().forEach((child, i) => {
|
|
152
|
+
const field = child.field;
|
|
153
|
+
const fieldName = field.field;
|
|
154
|
+
const shouldChange = i % 2 == 0;
|
|
155
|
+
if (shouldChange || fieldName == idField) {
|
|
156
|
+
let nv = newValue[fieldName];
|
|
157
|
+
if (shouldChange) nv = changeValue(nv, field);
|
|
158
|
+
if (nv === undefined) nv = null;
|
|
159
|
+
newValue[fieldName] = nv;
|
|
160
|
+
result[fieldName] = nv;
|
|
161
|
+
} else {
|
|
162
|
+
delete result[fieldName];
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
return { newValue, result };
|
|
166
|
+
}
|
package/test/gen.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import fc, { Arbitrary } from "fast-check";
|
|
2
|
+
import {
|
|
3
|
+
CompoundField,
|
|
4
|
+
createSchemaLookup,
|
|
5
|
+
FieldType,
|
|
6
|
+
isCompoundField,
|
|
7
|
+
makeSchemaDataNode,
|
|
8
|
+
SchemaDataNode,
|
|
9
|
+
SchemaField,
|
|
10
|
+
SchemaTags,
|
|
11
|
+
} from "../src";
|
|
12
|
+
import { newControl } from "@react-typed-forms/core";
|
|
13
|
+
|
|
14
|
+
export interface FieldAndValue {
|
|
15
|
+
field: SchemaField;
|
|
16
|
+
value: any;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function valueAndSchema(
|
|
20
|
+
options?: SchemaFieldGenOptions,
|
|
21
|
+
): Arbitrary<FieldAndValue> {
|
|
22
|
+
return randomSchemaField(options).chain((schema) =>
|
|
23
|
+
randomValueForField(schema).map((value) => ({ field: schema, value })),
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function makeDataNode(fv: FieldAndValue): SchemaDataNode {
|
|
28
|
+
return makeSchemaDataNode(
|
|
29
|
+
createSchemaLookup({ "": [fv.field] })
|
|
30
|
+
.getSchema("")!
|
|
31
|
+
.getChildNode(fv.field.field)!,
|
|
32
|
+
newControl(fv.value),
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface SchemaFieldGenOptions {
|
|
37
|
+
arrayChance?: number;
|
|
38
|
+
forceCompound?: boolean;
|
|
39
|
+
forceArray?: boolean;
|
|
40
|
+
compoundChance?: number;
|
|
41
|
+
idField?: boolean;
|
|
42
|
+
}
|
|
43
|
+
function randomSchemaField(
|
|
44
|
+
options: SchemaFieldGenOptions = {},
|
|
45
|
+
): Arbitrary<SchemaField> {
|
|
46
|
+
const {
|
|
47
|
+
arrayChance = 5,
|
|
48
|
+
compoundChance = 10,
|
|
49
|
+
forceCompound,
|
|
50
|
+
forceArray,
|
|
51
|
+
idField,
|
|
52
|
+
} = options;
|
|
53
|
+
const nextOptions = { arrayChance, compoundChance };
|
|
54
|
+
const field = fc.oneof(
|
|
55
|
+
{
|
|
56
|
+
weight: forceCompound ? 100 : compoundChance,
|
|
57
|
+
arbitrary: fc.constant(FieldType.Compound),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
weight: forceCompound ? 0 : 100 - compoundChance,
|
|
61
|
+
arbitrary: fc.constantFrom(
|
|
62
|
+
FieldType.String,
|
|
63
|
+
FieldType.Int,
|
|
64
|
+
FieldType.Double,
|
|
65
|
+
FieldType.Bool,
|
|
66
|
+
FieldType.Date,
|
|
67
|
+
FieldType.DateTime,
|
|
68
|
+
FieldType.Time,
|
|
69
|
+
),
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
const collection = fc.oneof(
|
|
73
|
+
{
|
|
74
|
+
weight: forceArray ? 0 : 100 - arrayChance,
|
|
75
|
+
arbitrary: fc.constant(false),
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
weight: forceArray ? 100 : arrayChance,
|
|
79
|
+
arbitrary: fc.constant(true),
|
|
80
|
+
},
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const withoutId = field.chain((fieldType) =>
|
|
84
|
+
fc.record({
|
|
85
|
+
field: fc.string(),
|
|
86
|
+
type: fc.constant(fieldType),
|
|
87
|
+
collection,
|
|
88
|
+
notNullable: fc.boolean(),
|
|
89
|
+
children:
|
|
90
|
+
fieldType == FieldType.Compound
|
|
91
|
+
? fc
|
|
92
|
+
.array(randomSchemaField(nextOptions), {
|
|
93
|
+
minLength: 1,
|
|
94
|
+
maxLength: 10,
|
|
95
|
+
})
|
|
96
|
+
.map((x) =>
|
|
97
|
+
Object.values(Object.fromEntries(x.map((y) => [y.field, y]))),
|
|
98
|
+
)
|
|
99
|
+
: fc.constant(null),
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
102
|
+
return !idField
|
|
103
|
+
? withoutId
|
|
104
|
+
: withoutId.chain((x) =>
|
|
105
|
+
fc.integer({ min: 0, max: (x.children?.length ?? 0) - 1 }).map((i) => ({
|
|
106
|
+
...x,
|
|
107
|
+
tags: [SchemaTags.IdField + x.children![i].field],
|
|
108
|
+
})),
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
function randomValueForField(
|
|
112
|
+
f: SchemaField,
|
|
113
|
+
element?: boolean,
|
|
114
|
+
): Arbitrary<any> {
|
|
115
|
+
return fc.integer({ min: 0, max: 100 }).chain(((nc) => {
|
|
116
|
+
if (nc <= 75 || f.notNullable) {
|
|
117
|
+
if (!element && f.collection) {
|
|
118
|
+
return fc.array(randomValueForField(f, true), {
|
|
119
|
+
minLength: 0,
|
|
120
|
+
maxLength: 10,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (f.type === FieldType.String) return fc.string();
|
|
124
|
+
if (f.type === FieldType.Int) return fc.integer();
|
|
125
|
+
if (f.type === FieldType.Double) return fc.double();
|
|
126
|
+
if (f.type === FieldType.Bool) return fc.boolean();
|
|
127
|
+
if (f.type === FieldType.Date)
|
|
128
|
+
return fc.date().map((x) => x.toISOString().substring(0, 10));
|
|
129
|
+
if (f.type === FieldType.DateTime)
|
|
130
|
+
return fc.date().map((x) => x.toISOString());
|
|
131
|
+
if (f.type === FieldType.Time)
|
|
132
|
+
return fc.date().map((x) => x.toISOString().substring(11));
|
|
133
|
+
if (isCompoundField(f))
|
|
134
|
+
return fc.record(
|
|
135
|
+
Object.fromEntries(
|
|
136
|
+
f.children.map((x) => [x.field, randomValueForField(x)]),
|
|
137
|
+
),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return fc.constantFrom(null, undefined);
|
|
141
|
+
}) as (x: number) => Arbitrary<any>);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function changeValue(
|
|
145
|
+
value: any,
|
|
146
|
+
field: SchemaField,
|
|
147
|
+
element?: boolean,
|
|
148
|
+
): any {
|
|
149
|
+
if (field.collection && !element) {
|
|
150
|
+
return [...(value ?? []), changeValue(undefined, field, true)];
|
|
151
|
+
}
|
|
152
|
+
switch (field.type) {
|
|
153
|
+
case FieldType.Compound:
|
|
154
|
+
const objValue = value ?? {};
|
|
155
|
+
return Object.fromEntries(
|
|
156
|
+
(field as CompoundField).children.map((x) => [
|
|
157
|
+
x.field,
|
|
158
|
+
changeValue(objValue[x.field], x),
|
|
159
|
+
]),
|
|
160
|
+
);
|
|
161
|
+
case FieldType.String:
|
|
162
|
+
case FieldType.Date:
|
|
163
|
+
case FieldType.DateTime:
|
|
164
|
+
case FieldType.Time:
|
|
165
|
+
return (value ?? "") + "x";
|
|
166
|
+
case FieldType.Int:
|
|
167
|
+
const v = value ?? 0;
|
|
168
|
+
return !v ? 1 : -v;
|
|
169
|
+
case FieldType.Double:
|
|
170
|
+
const dv = value ?? 0;
|
|
171
|
+
return !dv ? 1 : -dv;
|
|
172
|
+
case FieldType.Bool:
|
|
173
|
+
return !(value ?? false);
|
|
174
|
+
}
|
|
175
|
+
}
|
package/test/play.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { changeValue, FieldAndValue, makeDataNode } from "./gen";
|
|
2
|
+
import { getDiffObject } from "../src";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const fv = {
|
|
6
|
+
field: {
|
|
7
|
+
field: "",
|
|
8
|
+
type: "Compound",
|
|
9
|
+
collection: true,
|
|
10
|
+
notNullable: false,
|
|
11
|
+
children: [
|
|
12
|
+
{
|
|
13
|
+
field: "",
|
|
14
|
+
type: "String",
|
|
15
|
+
collection: false,
|
|
16
|
+
notNullable: false,
|
|
17
|
+
children: null,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
value: [{ "": "" }],
|
|
22
|
+
index: 0,
|
|
23
|
+
add: false,
|
|
24
|
+
} as FieldAndValue;
|
|
25
|
+
|
|
26
|
+
const dataNode = makeDataNode(fv);
|
|
27
|
+
const arrayControl = dataNode.control!;
|
|
28
|
+
let results: any = undefined;
|
|
29
|
+
arrayControl.as<any[]>().elements.forEach((control) => {
|
|
30
|
+
const result = { ...control.value };
|
|
31
|
+
const newValue = { ...control.value };
|
|
32
|
+
dataNode.schema.getChildNodes().forEach((child, i) => {
|
|
33
|
+
const field = child.field;
|
|
34
|
+
const fieldName = field.field;
|
|
35
|
+
if (i % 2 == 0) {
|
|
36
|
+
const nv = changeValue(newValue[fieldName], field);
|
|
37
|
+
newValue[fieldName] = nv;
|
|
38
|
+
result[fieldName] = nv;
|
|
39
|
+
} else {
|
|
40
|
+
delete result[fieldName];
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
control.value = newValue;
|
|
44
|
+
if (!results) results = [];
|
|
45
|
+
results.push(result);
|
|
46
|
+
});
|
|
47
|
+
console.log(fv.value);
|
|
48
|
+
console.log(arrayControl.value);
|
|
49
|
+
console.log(results);
|
|
50
|
+
console.log(getDiffObject(dataNode));
|