@strictly/react-form 0.0.1 → 0.0.2

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.
Files changed (173) hide show
  1. package/.out/core/mobx/field_adapter.d.ts +7 -6
  2. package/.out/core/mobx/field_adapter_builder.d.ts +12 -13
  3. package/.out/core/mobx/field_adapter_builder.js +8 -12
  4. package/.out/core/mobx/field_adapters_of_values.d.ts +4 -0
  5. package/.out/core/mobx/flattened_adapters_of_fields.d.ts +2 -2
  6. package/.out/core/mobx/flattened_list_types_of_type.d.ts +8 -0
  7. package/.out/core/mobx/form_fields_of_field_adapters.d.ts +8 -0
  8. package/.out/core/mobx/form_presenter.d.ts +21 -24
  9. package/.out/core/mobx/form_presenter.js +64 -69
  10. package/.out/core/mobx/merge_field_adapters_with_two_way_converter.d.ts +13 -0
  11. package/.out/core/mobx/merge_field_adapters_with_two_way_converter.js +11 -0
  12. package/.out/core/mobx/merge_field_adapters_with_validators.d.ts +11 -0
  13. package/.out/core/mobx/merge_field_adapters_with_validators.js +45 -0
  14. package/.out/core/mobx/specs/fixtures.d.ts +7 -0
  15. package/.out/core/mobx/specs/fixtures.js +20 -0
  16. package/.out/core/mobx/specs/flattened_adapters_of_fields.tests.js +5 -2
  17. package/.out/core/mobx/specs/{flattened_list_type_defs_of.tests.js → flattened_list_types_of_types.tests.js} +7 -7
  18. package/.out/core/mobx/specs/form_presenter.tests.js +162 -60
  19. package/.out/core/mobx/specs/merge_field_adapters_with_two_way_converter.js +89 -0
  20. package/.out/core/mobx/specs/merge_field_adapters_with_validators.tests.js +172 -0
  21. package/.out/core/mobx/types.d.ts +2 -2
  22. package/.out/field_converters/chain_field_converter.d.ts +3 -3
  23. package/.out/field_converters/chain_field_converter.js +17 -12
  24. package/.out/field_converters/identity_converter.d.ts +3 -3
  25. package/.out/field_converters/identity_converter.js +10 -6
  26. package/.out/field_converters/integer_to_string_converter.d.ts +5 -4
  27. package/.out/field_converters/integer_to_string_converter.js +13 -6
  28. package/.out/field_converters/list_converter.d.ts +2 -2
  29. package/.out/field_converters/list_converter.js +6 -1
  30. package/.out/field_converters/maybe_identity_converter.d.ts +3 -3
  31. package/.out/field_converters/maybe_identity_converter.js +3 -1
  32. package/.out/field_converters/nullable_to_boolean_converter.d.ts +9 -8
  33. package/.out/field_converters/nullable_to_boolean_converter.js +13 -7
  34. package/.out/field_converters/select_value_type_converter.d.ts +20 -15
  35. package/.out/field_converters/select_value_type_converter.js +29 -14
  36. package/.out/field_converters/specs/chain_field_converter.tests.d.ts +1 -0
  37. package/.out/field_converters/specs/chain_field_converter.tests.js +251 -0
  38. package/.out/field_converters/trimming_string_converter.d.ts +3 -3
  39. package/.out/field_converters/trimming_string_converter.js +7 -3
  40. package/.out/field_converters/validating_converter.d.ts +3 -3
  41. package/.out/field_converters/validating_converter.js +7 -5
  42. package/.out/index.d.ts +9 -2
  43. package/.out/index.js +9 -2
  44. package/.out/mantine/create_checkbox.d.ts +2 -3
  45. package/.out/mantine/create_checkbox.js +6 -5
  46. package/.out/mantine/create_pill.js +2 -2
  47. package/.out/mantine/create_radio.js +1 -1
  48. package/.out/mantine/create_radio_group.d.ts +2 -3
  49. package/.out/mantine/create_radio_group.js +4 -3
  50. package/.out/mantine/create_text_input.d.ts +2 -3
  51. package/.out/mantine/create_text_input.js +6 -5
  52. package/.out/mantine/create_value_input.d.ts +2 -3
  53. package/.out/mantine/create_value_input.js +6 -5
  54. package/.out/mantine/error_renderer.d.ts +6 -0
  55. package/.out/mantine/error_renderer.js +5 -0
  56. package/.out/mantine/hooks.d.ts +9 -13
  57. package/.out/mantine/hooks.js +10 -15
  58. package/.out/mantine/specs/checkbox_hooks.stories.d.ts +7 -2
  59. package/.out/mantine/specs/checkbox_hooks.stories.js +33 -6
  60. package/.out/mantine/specs/list_hooks.stories.js +2 -2
  61. package/.out/mantine/specs/radio_group_hooks.stories.d.ts +7 -2
  62. package/.out/mantine/specs/radio_group_hooks.stories.js +33 -6
  63. package/.out/mantine/specs/select_hooks.stories.d.ts +8 -2
  64. package/.out/mantine/specs/select_hooks.stories.js +45 -8
  65. package/.out/mantine/specs/text_input_hooks.stories.d.ts +5 -1
  66. package/.out/mantine/specs/text_input_hooks.stories.js +23 -8
  67. package/.out/mantine/specs/value_input_hooks.stories.d.ts +7 -2
  68. package/.out/mantine/specs/value_input_hooks.stories.js +49 -15
  69. package/.out/mantine/types.d.ts +4 -1
  70. package/.out/tsconfig.tsbuildinfo +1 -1
  71. package/.out/types/error_of_field.d.ts +2 -0
  72. package/.out/types/error_of_field.js +1 -0
  73. package/.out/types/field.d.ts +1 -1
  74. package/.out/types/field_converters.d.ts +17 -10
  75. package/.out/types/field_converters.js +5 -5
  76. package/.out/types/flattened_validators_of_fields.d.ts +8 -0
  77. package/.out/types/flattened_validators_of_fields.js +1 -0
  78. package/.out/types/merge_validators.d.ts +7 -0
  79. package/.out/types/merge_validators.js +38 -0
  80. package/.out/types/specs/flattened_validators_of_fields.tests.d.ts +1 -0
  81. package/.out/types/specs/flattened_validators_of_fields.tests.js +16 -0
  82. package/.out/types/specs/merge_validators.tests.d.ts +1 -0
  83. package/.out/types/specs/merge_validators.tests.js +192 -0
  84. package/.out/util/partial.d.ts +11 -5
  85. package/.out/util/partial.js +55 -15
  86. package/.turbo/turbo-build.log +9 -9
  87. package/.turbo/turbo-check-types.log +1 -1
  88. package/.turbo/turbo-release$colon$exports.log +1 -1
  89. package/README.md +5 -1
  90. package/core/mobx/field_adapter.ts +15 -7
  91. package/core/mobx/field_adapter_builder.ts +39 -75
  92. package/core/mobx/field_adapters_of_values.ts +17 -0
  93. package/core/mobx/flattened_adapters_of_fields.ts +3 -3
  94. package/core/mobx/flattened_list_types_of_type.ts +17 -0
  95. package/core/mobx/form_fields_of_field_adapters.ts +16 -0
  96. package/core/mobx/form_presenter.ts +117 -104
  97. package/core/mobx/merge_field_adapters_with_two_way_converter.ts +68 -0
  98. package/core/mobx/merge_field_adapters_with_validators.ts +99 -0
  99. package/core/mobx/specs/fixtures.ts +73 -0
  100. package/core/mobx/specs/flattened_adapters_of_fields.tests.ts +23 -2
  101. package/core/mobx/specs/flattened_list_types_of_types.tests.ts +35 -0
  102. package/core/mobx/specs/form_presenter.tests.ts +248 -124
  103. package/core/mobx/specs/merge_field_adapters_with_two_way_converter.ts +140 -0
  104. package/core/mobx/specs/merge_field_adapters_with_validators.tests.ts +259 -0
  105. package/core/mobx/types.ts +3 -3
  106. package/dist/index.cjs +459 -211
  107. package/dist/index.d.cts +153 -111
  108. package/dist/index.d.ts +153 -111
  109. package/dist/index.js +453 -200
  110. package/field_converters/chain_field_converter.ts +37 -23
  111. package/field_converters/identity_converter.ts +14 -10
  112. package/field_converters/integer_to_string_converter.ts +15 -9
  113. package/field_converters/list_converter.ts +8 -3
  114. package/field_converters/maybe_identity_converter.ts +7 -4
  115. package/field_converters/nullable_to_boolean_converter.ts +23 -16
  116. package/field_converters/select_value_type_converter.ts +86 -26
  117. package/field_converters/specs/chain_field_converter.tests.ts +302 -0
  118. package/field_converters/trimming_string_converter.ts +11 -6
  119. package/field_converters/validating_converter.ts +21 -11
  120. package/index.ts +9 -2
  121. package/mantine/create_checkbox.tsx +15 -8
  122. package/mantine/create_list.tsx +1 -4
  123. package/mantine/create_pill.tsx +2 -2
  124. package/mantine/create_radio.tsx +1 -1
  125. package/mantine/create_radio_group.tsx +8 -6
  126. package/mantine/create_text_input.tsx +20 -8
  127. package/mantine/create_value_input.tsx +17 -8
  128. package/mantine/error_renderer.ts +15 -0
  129. package/mantine/hooks.tsx +25 -51
  130. package/mantine/specs/__snapshots__/checkbox_hooks.tests.tsx.snap +126 -0
  131. package/mantine/specs/__snapshots__/radio_group_hooks.tests.tsx.snap +356 -0
  132. package/mantine/specs/__snapshots__/select_hooks.tests.tsx.snap +208 -12
  133. package/mantine/specs/__snapshots__/text_input_hooks.tests.tsx.snap +45 -0
  134. package/mantine/specs/__snapshots__/value_input_hooks.tests.tsx.snap +194 -8
  135. package/mantine/specs/checkbox_hooks.stories.tsx +47 -7
  136. package/mantine/specs/list_hooks.stories.tsx +2 -2
  137. package/mantine/specs/radio_group_hooks.stories.tsx +47 -7
  138. package/mantine/specs/select_hooks.stories.tsx +55 -8
  139. package/mantine/specs/text_input_hooks.stories.tsx +32 -7
  140. package/mantine/specs/value_input_hooks.stories.tsx +57 -16
  141. package/mantine/types.ts +5 -1
  142. package/package.json +16 -4
  143. package/tsconfig.json +1 -0
  144. package/types/error_of_field.ts +3 -0
  145. package/types/field.ts +1 -1
  146. package/types/field_converters.ts +21 -10
  147. package/types/flattened_validators_of_fields.ts +34 -0
  148. package/types/merge_validators.ts +80 -0
  149. package/types/specs/error_type_of_field.tests.ts +2 -2
  150. package/types/specs/flattened_validators_of_fields.tests.ts +93 -0
  151. package/types/specs/merge_validators.tests.ts +267 -0
  152. package/util/partial.tsx +200 -16
  153. package/.out/core/mobx/flattened_list_type_defs_of.d.ts +0 -8
  154. package/.out/field_validators/minimum_string_length_field_validator.d.ts +0 -2
  155. package/.out/field_validators/minimum_string_length_field_validator.js +0 -8
  156. package/.out/types/error_type_of_field.d.ts +0 -2
  157. package/.out/types/field_validator.d.ts +0 -3
  158. package/.out/types/flattened_form_fields_of.d.ts +0 -9
  159. package/.out/types/specs/flattened_form_fields_of.tests.js +0 -13
  160. package/core/mobx/flattened_list_type_defs_of.ts +0 -17
  161. package/core/mobx/specs/flattened_list_type_defs_of.tests.ts +0 -35
  162. package/field_validators/minimum_string_length_field_validator.ts +0 -13
  163. package/mantine/specs/__snapshots__/check_box_hooks.tests.tsx.snap +0 -227
  164. package/types/error_type_of_field.ts +0 -3
  165. package/types/field_validator.ts +0 -7
  166. package/types/flattened_form_fields_of.ts +0 -16
  167. package/types/specs/flattened_form_fields_of.tests.ts +0 -43
  168. /package/.out/core/mobx/{flattened_list_type_defs_of.js → field_adapters_of_values.js} +0 -0
  169. /package/.out/core/mobx/{specs/flattened_list_type_defs_of.tests.d.ts → flattened_list_types_of_type.js} +0 -0
  170. /package/.out/{types/error_type_of_field.js → core/mobx/form_fields_of_field_adapters.js} +0 -0
  171. /package/.out/{types/field_validator.js → core/mobx/specs/flattened_list_types_of_types.tests.d.ts} +0 -0
  172. /package/.out/{types/flattened_form_fields_of.js → core/mobx/specs/merge_field_adapters_with_two_way_converter.d.ts} +0 -0
  173. /package/.out/{types/specs/flattened_form_fields_of.tests.d.ts → core/mobx/specs/merge_field_adapters_with_validators.tests.d.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { type ToTypeOfFieldAdapter } from './field_adapter';
1
+ import { type ToOfFieldAdapter } from './field_adapter';
2
2
  import { type FlattenedConvertedFieldsOf, type FormPresenter } from './form_presenter';
3
3
  /**
4
4
  * Used to extract the supported value paths from a presenter
@@ -8,7 +8,7 @@ export type ValuePathsOfPresenter<Presenter extends FormPresenter<any, any, any,
8
8
  * Used to extract the render type (so the value that is passed to the view) of a given value path
9
9
  * from a presenter
10
10
  */
11
- export type ToTypeOfPresenterValuePath<Presenter extends FormPresenter<any, any, any, any>, K extends ValuePathsOfPresenter<Presenter>> = Presenter extends FormPresenter<infer _1, infer _2, infer _3, infer ValuePathsToAdapters> ? ToTypeOfFieldAdapter<ValuePathsToAdapters[K]> : never;
11
+ export type ToValueOfPresenterValuePath<Presenter extends FormPresenter<any, any, any, any>, K extends ValuePathsOfPresenter<Presenter>> = Presenter extends FormPresenter<infer _1, infer _2, infer _3, infer ValuePathsToAdapters> ? ToOfFieldAdapter<ValuePathsToAdapters[K]> : never;
12
12
  /**
13
13
  * Extracts the form fields from the presenter. The recommended way is to
14
14
  * define the form fields explicitly and use that type to enforce the types
@@ -1,3 +1,3 @@
1
- import { type FieldConverter, type SafeFieldConverter } from 'types/field_converters';
2
- export declare function chainFieldConverter<From, Intermediate, To, E1, E2, ValuePath extends string, Context>(from: FieldConverter<From, Intermediate, E1, ValuePath, Context>, to: FieldConverter<Intermediate, To, E2, ValuePath, Context>): FieldConverter<From, To, E1 | E2, ValuePath, Context>;
3
- export declare function chainSafeFieldConverter<From, Intermediate, To, ValuePath extends string, Context>(from: SafeFieldConverter<From, Intermediate, ValuePath, Context>, to: SafeFieldConverter<Intermediate, To, ValuePath, Context>): SafeFieldConverter<From, To, ValuePath, Context>;
1
+ import { type AnnotatedFieldConverter, type UnreliableFieldConverter } from 'types/field_converters';
2
+ export declare function chainUnreliableFieldConverter<From, Intermediate, To, E1, E2, ValuePath extends string, Context>(from: UnreliableFieldConverter<From, Intermediate, E1, ValuePath, Context>, to: UnreliableFieldConverter<Intermediate, To, E2, ValuePath, Context>): UnreliableFieldConverter<From, To, E1 | E2, ValuePath, Context>;
3
+ export declare function chainAnnotatedFieldConverter<From, Intermediate, To, ValuePath extends string, Context>(from: AnnotatedFieldConverter<From, Intermediate, ValuePath, Context>, to: AnnotatedFieldConverter<Intermediate, To, ValuePath, Context>): AnnotatedFieldConverter<From, To, ValuePath, Context>;
@@ -1,24 +1,24 @@
1
1
  import { UnreachableError, } from '@strictly/base';
2
- import { FieldConversionResult, } from 'types/field_converters';
3
- export function chainFieldConverter(from, to) {
2
+ import { UnreliableFieldConversionType, } from 'types/field_converters';
3
+ export function chainUnreliableFieldConverter(from, to) {
4
4
  return function (value, valuePath, context) {
5
5
  const fromConversion = from(value, valuePath, context);
6
6
  switch (fromConversion.type) {
7
- case FieldConversionResult.Success:
7
+ case UnreliableFieldConversionType.Success:
8
8
  return to(fromConversion.value, valuePath, context);
9
- case FieldConversionResult.Failure:
9
+ case UnreliableFieldConversionType.Failure:
10
10
  if (fromConversion.value != null) {
11
11
  const toConversion = to(fromConversion.value[0], valuePath, context);
12
12
  switch (toConversion.type) {
13
- case FieldConversionResult.Success:
13
+ case UnreliableFieldConversionType.Success:
14
14
  return {
15
- type: FieldConversionResult.Failure,
15
+ type: UnreliableFieldConversionType.Failure,
16
16
  error: fromConversion.error,
17
17
  value: [toConversion.value],
18
18
  };
19
- case FieldConversionResult.Failure:
19
+ case UnreliableFieldConversionType.Failure:
20
20
  return {
21
- type: FieldConversionResult.Failure,
21
+ type: UnreliableFieldConversionType.Failure,
22
22
  error: fromConversion.error,
23
23
  value: toConversion.value,
24
24
  };
@@ -28,7 +28,7 @@ export function chainFieldConverter(from, to) {
28
28
  }
29
29
  else {
30
30
  return {
31
- type: FieldConversionResult.Failure,
31
+ type: UnreliableFieldConversionType.Failure,
32
32
  error: fromConversion.error,
33
33
  value: null,
34
34
  };
@@ -38,9 +38,14 @@ export function chainFieldConverter(from, to) {
38
38
  }
39
39
  };
40
40
  }
41
- export function chainSafeFieldConverter(from, to) {
41
+ export function chainAnnotatedFieldConverter(from, to) {
42
42
  return function (value, valuePath, context) {
43
- const intermediate = from(value, valuePath, context);
44
- return to(intermediate, valuePath, context);
43
+ const { required: intermediateRequired, readonly: intermediateDisabled, value: intermediateValue, } = from(value, valuePath, context);
44
+ const { required: finalRequired, readonly: finalDisabled, value: finalValue, } = to(intermediateValue, valuePath, context);
45
+ return {
46
+ value: finalValue,
47
+ required: intermediateRequired || finalRequired,
48
+ readonly: intermediateDisabled || finalDisabled,
49
+ };
45
50
  };
46
51
  }
@@ -1,3 +1,3 @@
1
- import { type FieldConverter, type SafeFieldConverter } from 'types/field_converters';
2
- export declare function safeIdentityConverter<V, ValuePath extends string, Context>(): SafeFieldConverter<V, V, ValuePath, Context>;
3
- export declare function identityConverter<V, ValuePath extends string, Context>(): FieldConverter<V, V, never, ValuePath, Context>;
1
+ import { type AnnotatedFieldConverter, type UnreliableFieldConverter } from 'types/field_converters';
2
+ export declare function annotatedIdentityConverter<V, ValuePath extends string, Context>(required?: boolean): AnnotatedFieldConverter<V, V, ValuePath, Context>;
3
+ export declare function unreliableIdentityConverter<V, ValuePath extends string, Context>(): UnreliableFieldConverter<V, V, never, ValuePath, Context>;
@@ -1,13 +1,17 @@
1
- import { FieldConversionResult, } from 'types/field_converters';
2
- export function safeIdentityConverter() {
3
- return function (v) {
4
- return v;
1
+ import { UnreliableFieldConversionType, } from 'types/field_converters';
2
+ export function annotatedIdentityConverter(required = false) {
3
+ return function (value) {
4
+ return {
5
+ value,
6
+ required,
7
+ readonly: false,
8
+ };
5
9
  };
6
10
  }
7
- export function identityConverter() {
11
+ export function unreliableIdentityConverter() {
8
12
  return function (value) {
9
13
  return {
10
- type: FieldConversionResult.Success,
14
+ type: UnreliableFieldConversionType.Success,
11
15
  value,
12
16
  };
13
17
  };
@@ -1,7 +1,8 @@
1
- import { type FieldConversion, type TwoWayFieldConverter } from 'types/field_converters';
1
+ import { type AnnotatedFieldConversion, type TwoWayFieldConverter, type UnreliableFieldConversion } from 'types/field_converters';
2
2
  export declare class IntegerToStringConverter<E, ValuePath extends string, Context> implements TwoWayFieldConverter<number, string, E, ValuePath, Context> {
3
3
  private readonly isNanError;
4
- constructor(isNanError: E);
5
- convert(from: number): string;
6
- revert(from: string): FieldConversion<number, E>;
4
+ private readonly base;
5
+ constructor(isNanError: E, base?: number);
6
+ convert(from: number): AnnotatedFieldConversion<string>;
7
+ revert(from: string): UnreliableFieldConversion<number, E>;
7
8
  }
@@ -1,24 +1,31 @@
1
- import { FieldConversionResult, } from 'types/field_converters';
1
+ import { UnreliableFieldConversionType, } from 'types/field_converters';
2
2
  export class IntegerToStringConverter {
3
3
  isNanError;
4
- constructor(isNanError) {
4
+ base;
5
+ constructor(isNanError, base = 10) {
5
6
  this.isNanError = isNanError;
7
+ this.base = base;
6
8
  }
7
9
  convert(from) {
8
- return Math.floor(from).toString();
10
+ const value = Math.floor(from).toString();
11
+ return {
12
+ value,
13
+ required: false,
14
+ readonly: false,
15
+ };
9
16
  }
10
17
  revert(from) {
11
- const value = parseInt(from, 10);
18
+ const value = parseInt(from, this.base);
12
19
  if (Number.isNaN(value)) {
13
20
  return {
14
- type: FieldConversionResult.Failure,
21
+ type: UnreliableFieldConversionType.Failure,
15
22
  error: this.isNanError,
16
23
  value: null,
17
24
  };
18
25
  }
19
26
  else {
20
27
  return {
21
- type: FieldConversionResult.Success,
28
+ type: UnreliableFieldConversionType.Success,
22
29
  value,
23
30
  };
24
31
  }
@@ -1,2 +1,2 @@
1
- import { type SafeFieldConverter } from 'types/field_converters';
2
- export declare function listConverter<E, K extends string, ValuePath extends string, Context>(): SafeFieldConverter<readonly E[], K[], ValuePath, Context>;
1
+ import { type AnnotatedFieldConverter } from 'types/field_converters';
2
+ export declare function listConverter<E, K extends string, ValuePath extends string, Context>(): AnnotatedFieldConverter<readonly E[], K[], ValuePath, Context>;
@@ -1,8 +1,13 @@
1
1
  export function listConverter() {
2
2
  return function (from, valuePath) {
3
- return from.map(function (_v, i) {
3
+ const value = from.map(function (_v, i) {
4
4
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
5
5
  return `${valuePath}.${i}`;
6
6
  });
7
+ return {
8
+ value,
9
+ required: false,
10
+ readonly: false,
11
+ };
7
12
  };
8
13
  }
@@ -1,8 +1,8 @@
1
- import { type FieldConversion, type TwoWayFieldConverter } from 'types/field_converters';
1
+ import { type AnnotatedFieldConversion, type TwoWayFieldConverter, type UnreliableFieldConversion } from 'types/field_converters';
2
2
  export declare class MaybeIdentityConverter<From, To, E, ValuePath extends string, Context> implements TwoWayFieldConverter<From, From | To, E, ValuePath, Context> {
3
3
  private readonly converter;
4
4
  private readonly isFrom;
5
5
  constructor(converter: TwoWayFieldConverter<From, To, E, ValuePath, Context>, isFrom: (to: From | To) => to is From);
6
- convert(from: From, valuePath: ValuePath, context: Context): To | From;
7
- revert(from: To | From, valuePath: ValuePath, context: Context): FieldConversion<From, E>;
6
+ convert(from: From, valuePath: ValuePath, context: Context): AnnotatedFieldConversion<To | From>;
7
+ revert(from: To | From, valuePath: ValuePath, context: Context): UnreliableFieldConversion<From, E>;
8
8
  }
@@ -9,7 +9,9 @@ export class MaybeIdentityConverter {
9
9
  return this.converter.convert(from, valuePath, context);
10
10
  }
11
11
  revert(from, valuePath, context) {
12
- const value = this.isFrom(from) ? this.converter.convert(from, valuePath, context) : from;
12
+ const value = this.isFrom(from)
13
+ ? this.converter.convert(from, valuePath, context).value
14
+ : from;
13
15
  return this.converter.revert(value, valuePath, context);
14
16
  }
15
17
  }
@@ -1,11 +1,12 @@
1
- import { type ReadonlyTypeDefOf, type Type, type ValueTypeOf } from '@strictly/define';
2
- import { type FieldConversion, type TwoWayFieldConverterWithValueFactory } from 'types/field_converters';
3
- export declare class NullableToBooleanConverter<T extends Type, E, ValuePath extends string, Context> implements TwoWayFieldConverterWithValueFactory<ValueTypeOf<ReadonlyTypeDefOf<T>> | null, boolean, E, ValuePath, Context> {
1
+ import { type ReadonlyTypeOfType, type Type, type ValueOfType } from '@strictly/define';
2
+ import { type AnnotatedFieldConversion, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConversion } from 'types/field_converters';
3
+ export declare class NullableToBooleanConverter<T extends Type, E, ValuePath extends string, Context, NullType extends null | undefined> implements TwoWayFieldConverterWithValueFactory<ValueOfType<ReadonlyTypeOfType<T>> | NullType, boolean, E, ValuePath, Context> {
4
4
  private readonly typeDef;
5
5
  private readonly prototype;
6
- readonly defaultValue: ValueTypeOf<ReadonlyTypeDefOf<T>> | null;
7
- constructor(typeDef: T, prototype: ValueTypeOf<ReadonlyTypeDefOf<T>>, defaultToNull?: boolean);
8
- convert(from: ValueTypeOf<ReadonlyTypeDefOf<T>> | null): boolean;
9
- revert(from: boolean): FieldConversion<ValueTypeOf<ReadonlyTypeDefOf<T>> | null, E>;
10
- create(): ValueTypeOf<ReadonlyTypeDefOf<T>> | null;
6
+ private readonly nullType;
7
+ readonly defaultValue: ValueOfType<ReadonlyTypeOfType<T>> | NullType;
8
+ constructor(typeDef: T, prototype: ValueOfType<ReadonlyTypeOfType<T>>, nullType: NullType, defaultToNull?: boolean);
9
+ convert(from: ValueOfType<ReadonlyTypeOfType<T>> | NullType): AnnotatedFieldConversion<boolean>;
10
+ revert(from: boolean): UnreliableFieldConversion<ValueOfType<ReadonlyTypeOfType<T>> | NullType, E>;
11
+ create(): ValueOfType<ReadonlyTypeOfType<T>> | NullType;
11
12
  }
@@ -1,28 +1,34 @@
1
1
  import { copy, } from '@strictly/define';
2
- import { FieldConversionResult, } from 'types/field_converters';
2
+ import { UnreliableFieldConversionType, } from 'types/field_converters';
3
3
  export class NullableToBooleanConverter {
4
4
  typeDef;
5
5
  prototype;
6
+ nullType;
6
7
  defaultValue;
7
- constructor(typeDef, prototype, defaultToNull = true) {
8
+ constructor(typeDef, prototype, nullType, defaultToNull = true) {
8
9
  this.typeDef = typeDef;
9
10
  this.prototype = prototype;
10
- this.defaultValue = defaultToNull ? null : prototype;
11
+ this.nullType = nullType;
12
+ this.defaultValue = defaultToNull ? this.nullType : prototype;
11
13
  }
12
14
  convert(from) {
13
- return from != null;
15
+ return {
16
+ value: from !== this.nullType,
17
+ required: false,
18
+ readonly: false,
19
+ };
14
20
  }
15
21
  revert(from) {
16
22
  if (from) {
17
23
  const value = copy(this.typeDef, this.prototype);
18
24
  return {
19
- type: FieldConversionResult.Success,
25
+ type: UnreliableFieldConversionType.Success,
20
26
  value,
21
27
  };
22
28
  }
23
29
  return {
24
- type: FieldConversionResult.Success,
25
- value: null,
30
+ type: UnreliableFieldConversionType.Success,
31
+ value: this.nullType,
26
32
  };
27
33
  }
28
34
  create() {
@@ -1,23 +1,28 @@
1
- import { type StringKeyOf } from '@strictly/base';
2
- import { type LiteralTypeDef, type Type, type UnionTypeDef, type ValueTypeOf, type ValueTypesOfDiscriminatedUnion } from '@strictly/define';
3
- import { type FieldConversion, type TwoWayFieldConverterWithValueFactory } from 'types/field_converters';
4
- export declare abstract class AbstractSelectValueTypeConverter<T extends Type, To extends string | null, Values extends Readonly<Record<NonNullable<To>, ValueTypeOf<T>>>, NoSuchValueError, ValuePath extends string, Context> implements TwoWayFieldConverterWithValueFactory<ValueTypeOf<T>, keyof Values | null, NoSuchValueError, ValuePath, Context> {
1
+ import { type ExhaustiveArrayOfUnion, type StringKeyOf } from '@strictly/base';
2
+ import { type LiteralTypeDef, type ReadonlyTypeOfType, type Type, type UnionTypeDef, type ValueOfType, type ValueTypesOfDiscriminatedUnion } from '@strictly/define';
3
+ import { type AnnotatedFieldConversion, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConversion } from 'types/field_converters';
4
+ export declare abstract class AbstractSelectValueTypeConverter<T extends Type, From extends ValueOfType<T> | undefined, To extends string | null, Values extends Readonly<Record<NonNullable<To>, From>>, NoSuchValueError, ValuePath extends string, Context> implements TwoWayFieldConverterWithValueFactory<From, To, NoSuchValueError, ValuePath, Context> {
5
5
  protected readonly typeDef: T;
6
6
  protected readonly values: Values;
7
7
  private readonly defaultValueKey;
8
8
  private readonly noSuchValueError;
9
- constructor(typeDef: T, values: Values, defaultValueKey: keyof Values | null, noSuchValueError: NoSuchValueError | null);
10
- revert(from: keyof Values | null): FieldConversion<ValueTypeOf<T>, NoSuchValueError>;
11
- convert(from: ValueTypeOf<T>): To;
12
- protected abstract doConvert(from: ValueTypeOf<T>): To;
13
- create(): ValueTypeOf<T>;
9
+ private readonly required;
10
+ constructor(typeDef: T, values: Values, defaultValueKey: keyof Values | null | undefined, noSuchValueError: NoSuchValueError | null, required: boolean);
11
+ revert(from: To): UnreliableFieldConversion<From, NoSuchValueError>;
12
+ convert(from: From): AnnotatedFieldConversion<To>;
13
+ protected abstract doConvert(from: NonNullable<ValueOfType<T>>): To;
14
+ create(): From;
14
15
  }
15
- export declare class SelectDiscriminatedUnionConverter<U extends UnionTypeDef, To extends StringKeyOf<U['unions']> | null, ValuePath extends string, Context> extends AbstractSelectValueTypeConverter<Type<U>, To, ValueTypesOfDiscriminatedUnion<U>, never, ValuePath, Context> {
16
- constructor(typeDef: Type<U>, values: ValueTypesOfDiscriminatedUnion<U>, defaultValueKey: keyof U['unions']);
17
- protected doConvert(from: ValueTypeOf<Type<U>>): any;
16
+ export declare class SelectDiscriminatedUnionConverter<U extends UnionTypeDef, From extends ValueOfType<ReadonlyTypeOfType<Type<U>>> | (Required extends true ? never : undefined), To extends StringKeyOf<U['unions']> | null, ValuePath extends string, Context, Required extends boolean> extends AbstractSelectValueTypeConverter<Type<U>, From, To, ValueTypesOfDiscriminatedUnion<U>, never, ValuePath, Context> {
17
+ constructor(type: Type<U>, values: ValueTypesOfDiscriminatedUnion<U>, defaultValueKey: keyof U['unions'], required: Required);
18
+ protected doConvert(from: NonNullable<ValueOfType<Type<U>>>): any;
18
19
  }
19
- export declare class SelectLiteralConverter<L extends string | number | null, To extends string | null, Values extends Record<NonNullable<L>, NonNullable<To>>, NoSuchValueError, ValuePath extends string, Context> extends AbstractSelectValueTypeConverter<Type<LiteralTypeDef<L>>, To, Record<NonNullable<To>, L>, NoSuchValueError, ValuePath, Context> {
20
+ export declare class SelectLiteralConverter<L extends string | number | null, From extends L | (Required extends true ? never : undefined), To extends string | null, Values extends Record<NonNullable<From>, NonNullable<To>>, NoSuchValueError, ValuePath extends string, Context, Required extends boolean> extends AbstractSelectValueTypeConverter<Type<LiteralTypeDef<L>>, From, To, Record<NonNullable<To>, NonNullable<From>>, NoSuchValueError, ValuePath, Context> {
20
21
  private readonly valuesToStrings;
21
- constructor(typeDef: Type<LiteralTypeDef<L>>, valuesToStrings: Values, defaultValue: L | null, noSuchValueError: NoSuchValueError | null);
22
- protected doConvert(from: L): Values[NonNullable<L>];
22
+ constructor(typeDef: Type<LiteralTypeDef<L>>, valuesToStrings: Values, defaultValue: From, noSuchValueError: NoSuchValueError | null, required: Required);
23
+ protected doConvert(from: NonNullable<From>): Values[NonNullable<From>];
24
+ }
25
+ export declare class SelectStringConverter<L extends string | null, From extends L | undefined, A extends readonly NonNullable<From>[], NoSuchValueError, ValuePath extends string, Context> extends AbstractSelectValueTypeConverter<Type<LiteralTypeDef<L>>, From, string | null, Record<string, From>, NoSuchValueError, ValuePath, Context> {
26
+ constructor(typeDef: Type<LiteralTypeDef<L>>, allowedValues: ExhaustiveArrayOfUnion<NonNullable<From>, A>, defaultValue: L | undefined, noSuchValueError: NoSuchValueError | null, required?: boolean);
27
+ protected doConvert(from: NonNullable<L>): NonNullable<L>;
23
28
  }
@@ -1,47 +1,51 @@
1
1
  import { reverse, } from '@strictly/base';
2
2
  import { copy, } from '@strictly/define';
3
- import { FieldConversionResult, } from 'types/field_converters';
3
+ import { UnreliableFieldConversionType, } from 'types/field_converters';
4
4
  export class AbstractSelectValueTypeConverter {
5
5
  typeDef;
6
6
  values;
7
7
  defaultValueKey;
8
8
  noSuchValueError;
9
- constructor(typeDef, values, defaultValueKey, noSuchValueError) {
9
+ required;
10
+ constructor(typeDef, values, defaultValueKey, noSuchValueError, required) {
10
11
  this.typeDef = typeDef;
11
12
  this.values = values;
12
13
  this.defaultValueKey = defaultValueKey;
13
14
  this.noSuchValueError = noSuchValueError;
15
+ this.required = required;
14
16
  }
15
17
  revert(from) {
16
18
  const prototype = from == null ? null : this.values[from];
17
19
  if (prototype == null && this.noSuchValueError != null) {
18
20
  return {
19
- type: FieldConversionResult.Failure,
21
+ type: UnreliableFieldConversionType.Failure,
20
22
  error: this.noSuchValueError,
21
23
  value: null,
22
24
  };
23
25
  }
24
- const value = prototype == null ? null : copy(this.typeDef, prototype);
26
+ const value = prototype == null ? prototype : copy(this.typeDef, prototype);
25
27
  // TODO given we are dealing with strings, maybe we should have a check to make sure value is in the record
26
28
  // of values?
27
29
  return {
28
- type: FieldConversionResult.Success,
30
+ type: UnreliableFieldConversionType.Success,
29
31
  value: value,
30
32
  };
31
33
  }
32
34
  convert(from) {
33
- if (from == null) {
34
- return null;
35
- }
36
- return this.doConvert(from);
35
+ const value = from == null ? from : this.doConvert(from);
36
+ return {
37
+ value,
38
+ required: this.required,
39
+ readonly: false,
40
+ };
37
41
  }
38
42
  create() {
39
43
  return this.defaultValueKey != null ? this.values[this.defaultValueKey] : null;
40
44
  }
41
45
  }
42
46
  export class SelectDiscriminatedUnionConverter extends AbstractSelectValueTypeConverter {
43
- constructor(typeDef, values, defaultValueKey) {
44
- super(typeDef, values, defaultValueKey, null);
47
+ constructor(type, values, defaultValueKey, required) {
48
+ super(type, values, defaultValueKey, null, required);
45
49
  }
46
50
  doConvert(from) {
47
51
  const { definition: { discriminator, }, } = this.typeDef;
@@ -50,11 +54,22 @@ export class SelectDiscriminatedUnionConverter extends AbstractSelectValueTypeCo
50
54
  }
51
55
  export class SelectLiteralConverter extends AbstractSelectValueTypeConverter {
52
56
  valuesToStrings;
53
- constructor(typeDef, valuesToStrings, defaultValue, noSuchValueError) {
54
- super(typeDef, reverse(valuesToStrings), defaultValue && valuesToStrings[defaultValue], noSuchValueError);
57
+ constructor(typeDef, valuesToStrings, defaultValue, noSuchValueError, required) {
58
+ super(typeDef, reverse(valuesToStrings), defaultValue && valuesToStrings[defaultValue], noSuchValueError, required);
55
59
  this.valuesToStrings = valuesToStrings;
56
60
  }
57
61
  doConvert(from) {
58
- return from && this.valuesToStrings[from];
62
+ return this.valuesToStrings[from];
63
+ }
64
+ }
65
+ export class SelectStringConverter extends AbstractSelectValueTypeConverter {
66
+ constructor(typeDef, allowedValues, defaultValue, noSuchValueError, required = false) {
67
+ super(typeDef, allowedValues.reduce(function (acc, value) {
68
+ acc[value] = value;
69
+ return acc;
70
+ }, {}), defaultValue, noSuchValueError, required);
71
+ }
72
+ doConvert(from) {
73
+ return from;
59
74
  }
60
75
  }