@strictly/react-form 0.0.6 → 0.0.7
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/.out/core/mobx/specs/form_presenter.tests.js +3 -6
- package/.out/core/mobx/specs/{merge_field_adapters_with_two_way_converter.js → merge_field_adapters_with_two_way_converter.tests.js} +15 -16
- package/.out/core/mobx/specs/sub_form_field_adapters.tests.js +78 -10
- package/.out/core/mobx/sub_form_field_adapters.d.ts +6 -4
- package/.out/core/mobx/sub_form_field_adapters.js +23 -2
- package/.out/tsconfig.tsbuildinfo +1 -1
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-check-types.log +1 -1
- package/.turbo/turbo-release$colon$exports.log +1 -1
- package/core/mobx/specs/form_presenter.tests.ts +6 -6
- package/core/mobx/specs/{merge_field_adapters_with_two_way_converter.ts → merge_field_adapters_with_two_way_converter.tests.ts} +16 -16
- package/core/mobx/specs/sub_form_field_adapters.tests.ts +93 -10
- package/core/mobx/sub_form_field_adapters.ts +54 -7
- package/dist/index.cjs +33 -13
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +24 -2
- package/package.json +1 -1
- /package/.out/core/mobx/specs/{merge_field_adapters_with_two_way_converter.d.ts → merge_field_adapters_with_two_way_converter.tests.d.ts} +0 -0
|
@@ -21,18 +21,16 @@ describe('all', function () {
|
|
|
21
21
|
describe('FlattenedTypePathsToConvertersOf', function () {
|
|
22
22
|
describe('record', function () {
|
|
23
23
|
const typeDef = record(numberType);
|
|
24
|
-
let t;
|
|
25
24
|
it('equals expected type', function () {
|
|
26
|
-
expectTypeOf(
|
|
25
|
+
expectTypeOf().toEqualTypeOf();
|
|
27
26
|
});
|
|
28
27
|
});
|
|
29
28
|
describe('object', function () {
|
|
30
29
|
const typeDef = object()
|
|
31
30
|
.field('x', stringType)
|
|
32
31
|
.field('y', booleanType);
|
|
33
|
-
let t;
|
|
34
32
|
it('equals expected type', function () {
|
|
35
|
-
expectTypeOf(
|
|
33
|
+
expectTypeOf().toEqualTypeOf();
|
|
36
34
|
});
|
|
37
35
|
it('matches representative adapters', function () {
|
|
38
36
|
expectTypeOf().toMatchTypeOf();
|
|
@@ -50,9 +48,8 @@ describe('all', function () {
|
|
|
50
48
|
'$.b': '$.y',
|
|
51
49
|
'$.c': '$.z',
|
|
52
50
|
};
|
|
53
|
-
let t;
|
|
54
51
|
it('equals expected type', function () {
|
|
55
|
-
expectTypeOf(
|
|
52
|
+
expectTypeOf().toEqualTypeOf();
|
|
56
53
|
});
|
|
57
54
|
});
|
|
58
55
|
});
|
|
@@ -9,9 +9,8 @@ const error3 = Symbol();
|
|
|
9
9
|
const error4 = Symbol();
|
|
10
10
|
const context = Symbol();
|
|
11
11
|
describe('MergedOfFieldAdapterWithTwoWayConverter', function () {
|
|
12
|
-
let m;
|
|
13
12
|
it('merges the errors', function () {
|
|
14
|
-
expectTypeOf().toEqualTypeOf(
|
|
13
|
+
expectTypeOf().toEqualTypeOf();
|
|
15
14
|
});
|
|
16
15
|
});
|
|
17
16
|
const originalIntegerAdapter = identityAdapter(0);
|
|
@@ -69,20 +68,20 @@ describe('mergeFieldAdaptersWithTwoWayConverter', function () {
|
|
|
69
68
|
beforeEach(function () {
|
|
70
69
|
result = merged.booleanAdapter.revert(true, 'booleanAdapter', context);
|
|
71
70
|
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
71
|
+
it('returns the same value on revert', function () {
|
|
72
|
+
expect(result).toEqual(expect.objectContaining({
|
|
73
|
+
value: true,
|
|
74
|
+
type: UnreliableFieldConversionType.Success,
|
|
75
|
+
}));
|
|
76
|
+
});
|
|
77
|
+
it('calls the mocked converter', function () {
|
|
78
|
+
expect(converter.revert).toHaveBeenCalledOnce();
|
|
79
|
+
expect(converter.revert).toHaveBeenCalledWith(true, 'booleanAdapter', context);
|
|
80
|
+
});
|
|
81
|
+
it('calls the mocked adapter', function () {
|
|
82
|
+
expect(booleanAdapter.revert).toHaveBeenCalledOnce();
|
|
83
|
+
expect(booleanAdapter.revert).toHaveBeenCalledWith(true, 'booleanAdapter', context);
|
|
84
|
+
});
|
|
86
85
|
});
|
|
87
86
|
});
|
|
88
87
|
});
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { numberType, object, stringType, } from '@strictly/define';
|
|
1
2
|
import { subFormFieldAdapters, } from 'core/mobx/sub_form_field_adapters';
|
|
3
|
+
import { UnreliableFieldConversionType } from 'types/field_converters';
|
|
2
4
|
import { mockDeep } from 'vitest-mock-extended';
|
|
3
5
|
describe('subFormFieldAdapters', () => {
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
+
const mockedFieldAdapter1 = mockDeep();
|
|
7
|
+
const fieldAdapter1 = mockedFieldAdapter1;
|
|
8
|
+
const mockedFieldAdapter2 = mockDeep();
|
|
9
|
+
const fieldAdapter2 = mockedFieldAdapter2;
|
|
6
10
|
describe('empty value', () => {
|
|
7
|
-
const adapters = subFormFieldAdapters({}, '$.a');
|
|
11
|
+
const adapters = subFormFieldAdapters({}, '$.a', stringType);
|
|
8
12
|
it('equals expected type', () => {
|
|
9
13
|
expectTypeOf(adapters).toEqualTypeOf();
|
|
10
14
|
});
|
|
@@ -13,28 +17,92 @@ describe('subFormFieldAdapters', () => {
|
|
|
13
17
|
});
|
|
14
18
|
});
|
|
15
19
|
describe('single adapter', () => {
|
|
20
|
+
const type = object().field('a', stringType);
|
|
16
21
|
const adapters = subFormFieldAdapters({
|
|
17
22
|
$: fieldAdapter1,
|
|
18
|
-
}, '$.a');
|
|
23
|
+
}, '$.a', type);
|
|
19
24
|
it('equals expected type', () => {
|
|
20
|
-
|
|
25
|
+
// TODO toEqualTypeOf (seems to be a TS error)
|
|
26
|
+
expectTypeOf(adapters).toMatchTypeOf();
|
|
21
27
|
});
|
|
22
28
|
it('equals expected value', () => {
|
|
23
|
-
expect(adapters).toEqual({ '$.a':
|
|
29
|
+
expect(adapters).toEqual({ '$.a': expect.anything() });
|
|
30
|
+
});
|
|
31
|
+
it('calls convert with the correct paths and values', () => {
|
|
32
|
+
const mockedReturnedValue = {
|
|
33
|
+
value: false,
|
|
34
|
+
required: false,
|
|
35
|
+
readonly: false,
|
|
36
|
+
};
|
|
37
|
+
mockedFieldAdapter1.convert.mockReturnValue(mockedReturnedValue);
|
|
38
|
+
const returnedValue = adapters['$.a'].convert('x', '$.a', { a: 'y' });
|
|
39
|
+
expect(fieldAdapter1.convert).toHaveBeenCalledWith('x', '$', 'y');
|
|
40
|
+
expect(returnedValue).toEqual(mockedReturnedValue);
|
|
41
|
+
});
|
|
42
|
+
it('calls revert with the correct paths and values', () => {
|
|
43
|
+
const mockedReturnedValue = {
|
|
44
|
+
type: UnreliableFieldConversionType.Success,
|
|
45
|
+
value: 'ok',
|
|
46
|
+
};
|
|
47
|
+
mockedFieldAdapter1.revert.mockReturnValue(mockedReturnedValue);
|
|
48
|
+
const returnedValue = adapters['$.a'].revert?.(true, '$.a', { a: 'y' });
|
|
49
|
+
expect(fieldAdapter1.revert).toHaveBeenCalledWith(true, '$', 'y');
|
|
50
|
+
expect(returnedValue).toEqual(mockedReturnedValue);
|
|
51
|
+
});
|
|
52
|
+
it('calls create with the correct paths and values', () => {
|
|
53
|
+
const mockedReturnedValue = 'x';
|
|
54
|
+
mockedFieldAdapter1.create.mockReturnValue(mockedReturnedValue);
|
|
55
|
+
const returnedValue = adapters['$.a'].create('$.a', { a: 'y' });
|
|
56
|
+
expect(fieldAdapter1.create).toHaveBeenCalledWith('$', 'y');
|
|
57
|
+
expect(returnedValue).toEqual(mockedReturnedValue);
|
|
24
58
|
});
|
|
25
59
|
});
|
|
26
60
|
describe('multiple adapters', () => {
|
|
61
|
+
const type = object()
|
|
62
|
+
.field('a', object().field('x', stringType).field('y', numberType));
|
|
27
63
|
const adapters = subFormFieldAdapters({
|
|
28
64
|
'$.x': fieldAdapter1,
|
|
29
65
|
'$.y': fieldAdapter2,
|
|
30
|
-
}, '$.a');
|
|
66
|
+
}, '$.a', type);
|
|
31
67
|
it('equals expected type', () => {
|
|
32
|
-
|
|
68
|
+
// TODO toEqualTypeOf (seems to be a TS error)
|
|
69
|
+
expectTypeOf(adapters).toMatchTypeOf();
|
|
33
70
|
});
|
|
34
71
|
it('equals expected value', () => {
|
|
35
72
|
expect(adapters).toEqual({
|
|
36
|
-
'$.a.x':
|
|
37
|
-
'$.a.y':
|
|
73
|
+
'$.a.x': expect.anything(),
|
|
74
|
+
'$.a.y': expect.anything(),
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('calls convert with correct paths and values', () => {
|
|
78
|
+
const subContext = {
|
|
79
|
+
x: 'a',
|
|
80
|
+
y: 1,
|
|
81
|
+
};
|
|
82
|
+
const context = {
|
|
83
|
+
a: subContext,
|
|
84
|
+
};
|
|
85
|
+
it('calls $.a.x', () => {
|
|
86
|
+
const mockedReturnedValue = {
|
|
87
|
+
value: true,
|
|
88
|
+
readonly: true,
|
|
89
|
+
required: false,
|
|
90
|
+
};
|
|
91
|
+
mockedFieldAdapter1.convert.mockReturnValue(mockedReturnedValue);
|
|
92
|
+
const returnedValue = adapters['$.a.x'].convert('b', '$.a.x', context);
|
|
93
|
+
expect(fieldAdapter1.convert).toHaveBeenCalledWith('b', '$.x', subContext);
|
|
94
|
+
expect(returnedValue).toEqual(mockedReturnedValue);
|
|
95
|
+
});
|
|
96
|
+
it('calls $.a.y', () => {
|
|
97
|
+
const mockedReturnedValue = {
|
|
98
|
+
value: false,
|
|
99
|
+
readonly: false,
|
|
100
|
+
required: false,
|
|
101
|
+
};
|
|
102
|
+
mockedFieldAdapter2.convert.mockReturnValue(mockedReturnedValue);
|
|
103
|
+
const returnedValue = adapters['$.a.y'].convert(2, '$.a.y', context);
|
|
104
|
+
expect(fieldAdapter2.convert).toHaveBeenCalledWith(2, '$.y', subContext);
|
|
105
|
+
expect(returnedValue).toEqual(mockedReturnedValue);
|
|
38
106
|
});
|
|
39
107
|
});
|
|
40
108
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type StringConcatOf } from '@strictly/base';
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { type Type, type ValueOfType } from '@strictly/define';
|
|
3
|
+
import { type ErrorOfFieldAdapter, type FieldAdapter, type FromOfFieldAdapter, type ToOfFieldAdapter } from './field_adapter';
|
|
4
|
+
type SubFormFieldAdapter<F extends FieldAdapter, P extends string, Context> = FieldAdapter<FromOfFieldAdapter<F>, ToOfFieldAdapter<F>, ErrorOfFieldAdapter<F>, P, Context>;
|
|
5
|
+
type SubFormFieldAdapters<SubAdapters extends Record<string, FieldAdapter>, P extends string, Context> = {
|
|
6
|
+
[K in keyof SubAdapters as K extends StringConcatOf<'$', infer S> ? `${P}${S}` : never]: K extends StringConcatOf<'$', infer S> ? SubFormFieldAdapter<SubAdapters[K], `${P}${S}`, Context> : never;
|
|
5
7
|
};
|
|
6
|
-
export declare function subFormFieldAdapters<SubAdapters extends Record<string, FieldAdapter>, P extends string>(subAdapters: SubAdapters, prefix: P): SubFormFieldAdapters<SubAdapters, P
|
|
8
|
+
export declare function subFormFieldAdapters<SubAdapters extends Record<string, FieldAdapter>, P extends string, ContextType extends Type>(subAdapters: SubAdapters, prefix: P, contextType: ContextType): SubFormFieldAdapters<SubAdapters, P, ValueOfType<ContextType>>;
|
|
7
9
|
export {};
|
|
@@ -1,8 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
import { flattenValuesOfType, } from '@strictly/define';
|
|
2
|
+
export function subFormFieldAdapters(subAdapters, prefix, contextType) {
|
|
3
|
+
function getSubValuePathAndContext(valuePath, context) {
|
|
4
|
+
const subValuePath = valuePath.replace(prefix, '$');
|
|
5
|
+
const subContext = flattenValuesOfType(contextType, context)[prefix];
|
|
6
|
+
return [
|
|
7
|
+
subValuePath,
|
|
8
|
+
subContext,
|
|
9
|
+
];
|
|
10
|
+
}
|
|
2
11
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
3
12
|
return Object.entries(subAdapters).reduce((acc, [subKey, subValue,]) => {
|
|
4
13
|
const key = subKey.replace('$', prefix);
|
|
5
|
-
|
|
14
|
+
// adapt field adapter with new path and context
|
|
15
|
+
const adaptedAdapter = {
|
|
16
|
+
convert: (from, valuePath, context) => {
|
|
17
|
+
return subValue.convert(from, ...getSubValuePathAndContext(valuePath, context));
|
|
18
|
+
},
|
|
19
|
+
create: (valuePath, context) => {
|
|
20
|
+
return subValue.create(...getSubValuePathAndContext(valuePath, context));
|
|
21
|
+
},
|
|
22
|
+
revert: subValue.revert && ((from, valuePath, context) => {
|
|
23
|
+
return subValue.revert(from, ...getSubValuePathAndContext(valuePath, context));
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
acc[key] = adaptedAdapter;
|
|
6
27
|
return acc;
|
|
7
28
|
}, {});
|
|
8
29
|
}
|