@strictly/react-form 0.0.31 → 0.0.32

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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Maybe, ElementOfArray, StringConcatOf, StringKeyOf as StringKeyOf$1, ExhaustiveArrayOfUnion, FriendlyExhaustiveArrayOfUnion } from '@strictly/base';
2
- import { Type, ValueOfType, ReadonlyTypeOfType, FlattenedTypesOfType, ListTypeDef, FlattenedValuesOfType, MobxValueOfType, Accessor, Validator, UnionTypeDef, ValueTypesOfDiscriminatedUnion, LiteralTypeDef } from '@strictly/define';
2
+ import { Type, ValueOfType, ReadonlyTypeOfType, FlattenedTypesOfType, ListTypeDef, FlattenedValuesOfType, Accessor, Validator, UnionTypeDef, ValueTypesOfDiscriminatedUnion, LiteralTypeDef } from '@strictly/define';
3
3
  import { ValueOf, SimplifyDeep, ReadonlyDeep, UnionToIntersection, StringKeyOf, Simplify } from 'type-fest';
4
4
  import { ComponentType, RefAttributes, ComponentProps, ForwardRefExoticComponent, PropsWithoutRef, Ref, DependencyList } from 'react';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -136,7 +136,7 @@ declare abstract class FormModel<T extends Type, ValueToTypePaths extends Readon
136
136
  private readonly originalValue;
137
137
  protected readonly adapters: TypePathsToAdapters;
138
138
  protected readonly mode: FormMode;
139
- accessor value: MobxValueOfType<T>;
139
+ private accessor observableValue;
140
140
  accessor fieldOverrides: FlattenedFieldOverrides<ValuePathsToAdapters>;
141
141
  accessor errorOverrides: FlattenedErrorOverrides<ValuePathsToAdapters>;
142
142
  accessor validation: FlattenedValidation<ValuePathsToAdapters>;
@@ -146,6 +146,7 @@ declare abstract class FormModel<T extends Type, ValueToTypePaths extends Readon
146
146
  constructor(type: T, originalValue: ValueOfType<ReadonlyTypeOfType<T>>, adapters: TypePathsToAdapters, mode: FormMode);
147
147
  protected abstract toContext(value: ValueOfType<ReadonlyTypeOfType<T>>, valuePath: keyof ValuePathsToAdapters): ContextType;
148
148
  get forceMutableFields(): boolean;
149
+ get value(): ValueOfType<ReadonlyTypeOfType<T>>;
149
150
  get fields(): SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>>;
150
151
  private get knownFields();
151
152
  private maybeSynthesizeFieldByValuePath;
@@ -210,6 +211,12 @@ type MergedOfFieldAdaptersWithValidators<FieldAdapters extends Readonly<Record<K
210
211
  type MergedOfFieldAdapterWithValidator<A extends FieldAdapter, V extends Validator | undefined> = undefined extends V ? A : A extends FieldAdapter<infer From, infer To, infer E1, infer P1, infer C1> ? V extends Validator<From, infer E2, infer P2, infer C2> ? FieldAdapter<From, To, E1 | E2, P1 | P2, C1 & C2> : never : never;
211
212
  declare function mergeAdaptersWithValidators<FieldAdapters extends Readonly<Record<Key, FieldAdapter>>, Validators extends Readonly<Record<string, Validator>>, Key extends keyof Validators = keyof Validators>(adapters: FieldAdapters, validators: Validators): MergedOfFieldAdaptersWithValidators<FieldAdapters, Validators, Key>;
212
213
 
214
+ /**
215
+ * Used for when you want to look at the value of an observable without observing it (or triggering
216
+ * the mobx runtime linter)
217
+ */
218
+ declare function peek<T>(operation: () => T): T;
219
+
213
220
  type SubFormFieldAdapter<F extends FieldAdapter, ValuePath extends string> = FieldAdapter<FromOfFieldAdapter<F>, ToOfFieldAdapter<F>, ErrorOfFieldAdapter<F>, ValuePathOfFieldAdapter<F> extends StringConcatOf<'$', infer ValuePathSuffix> ? `${ValuePath}${ValuePathSuffix}` : string, ContextOfFieldAdapter<F>>;
214
221
  type SubFormFieldAdapters<SubAdapters extends Record<string, FieldAdapter>, TypePath extends string, ValuePath extends string> = {
215
222
  [K in keyof SubAdapters as K extends StringConcatOf<'$', infer TypePathSuffix> ? `${TypePath}${TypePathSuffix}` : never]: SubFormFieldAdapter<SubAdapters[K], ValuePath>;
@@ -459,4 +466,4 @@ declare function mergeValidators<Validators1 extends Partial<Readonly<Record<Key
459
466
 
460
467
  declare function Empty(): null;
461
468
 
462
- export { AbstractSelectValueTypeConverter, type AnnotatedFieldConversion, type AnnotatedFieldConverter, type Annotation, type ContextOf, type ContextOfFieldAdapter, DefaultErrorRenderer, Empty, type ErrorOfField, type ErrorOfFieldAdapter, type ErrorRenderer, type ErrorRendererProps, type Field, type FieldAdapter, type FieldAdaptersOfValues, type FieldValueFactory, type Fields, type FieldsViewProps, type FlattenedAdaptersOfFields, type FlattenedConvertedFieldsOf, type FlattenedTypePathsToAdaptersOf, type FormFieldsOfFieldAdapters, type FormMode, FormModel, type FormProps, type FromOfFieldAdapter, IntegerToStringConverter, type MergedOfFieldAdaptersWithTwoWayConverter, type MergedOfFieldAdaptersWithValidators, type MergedOfValidator, type MergedOfValidators, NullableToBooleanConverter, type PartialComponent, type RefOfProps, SelectDiscriminatedUnionConverter, SelectLiteralConverter, SelectStringConverter, type ToOfFieldAdapter, TrimmingStringConverter, type TwoWayFieldConverter, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConversion, UnreliableFieldConversionType, type UnreliableFieldConverter, type UnsafePartialComponent, Validation, type ValuePathOfFieldAdapter, type ValuePathsToAdaptersOf, adapter, adapterFromPrototype, adapterFromTwoWayConverter, createPartialComponent, createPartialObserverComponent, createSimplePartialComponent, createUnsafePartialObserverComponent, identityAdapter, listAdapter, mergeAdaptersWithValidators, mergeFieldAdaptersWithTwoWayConverter, mergeValidators, prototypingFieldValueFactory, subFormFieldAdapters, trimmingStringAdapter, useDefaultMobxFormHooks, useMantineFormFields, usePartialComponent, usePartialObserverComponent, validatingConverter };
469
+ export { AbstractSelectValueTypeConverter, type AnnotatedFieldConversion, type AnnotatedFieldConverter, type Annotation, type ContextOf, type ContextOfFieldAdapter, DefaultErrorRenderer, Empty, type ErrorOfField, type ErrorOfFieldAdapter, type ErrorRenderer, type ErrorRendererProps, type Field, type FieldAdapter, type FieldAdaptersOfValues, type FieldValueFactory, type Fields, type FieldsViewProps, type FlattenedAdaptersOfFields, type FlattenedConvertedFieldsOf, type FlattenedTypePathsToAdaptersOf, type FormFieldsOfFieldAdapters, type FormMode, FormModel, type FormProps, type FromOfFieldAdapter, IntegerToStringConverter, type MergedOfFieldAdaptersWithTwoWayConverter, type MergedOfFieldAdaptersWithValidators, type MergedOfValidator, type MergedOfValidators, NullableToBooleanConverter, type PartialComponent, type RefOfProps, SelectDiscriminatedUnionConverter, SelectLiteralConverter, SelectStringConverter, type ToOfFieldAdapter, TrimmingStringConverter, type TwoWayFieldConverter, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConversion, UnreliableFieldConversionType, type UnreliableFieldConverter, type UnsafePartialComponent, Validation, type ValuePathOfFieldAdapter, type ValuePathsToAdaptersOf, adapter, adapterFromPrototype, adapterFromTwoWayConverter, createPartialComponent, createPartialObserverComponent, createSimplePartialComponent, createUnsafePartialObserverComponent, identityAdapter, listAdapter, mergeAdaptersWithValidators, mergeFieldAdaptersWithTwoWayConverter, mergeValidators, peek, prototypingFieldValueFactory, subFormFieldAdapters, trimmingStringAdapter, useDefaultMobxFormHooks, useMantineFormFields, usePartialComponent, usePartialObserverComponent, validatingConverter };
package/dist/index.js CHANGED
@@ -312,6 +312,7 @@ import {
312
312
  UnreachableError as UnreachableError2
313
313
  } from "@strictly/base";
314
314
  import {
315
+ copy,
315
316
  equals,
316
317
  flattenAccessorsOfType,
317
318
  flattenTypesOfType,
@@ -322,6 +323,7 @@ import {
322
323
  valuePathToTypePath
323
324
  } from "@strictly/define";
324
325
  import {
326
+ action,
325
327
  computed,
326
328
  observable,
327
329
  runInAction
@@ -332,8 +334,8 @@ var Validation = /* @__PURE__ */ ((Validation2) => {
332
334
  Validation2[Validation2["Always"] = 2] = "Always";
333
335
  return Validation2;
334
336
  })(Validation || {});
335
- var _valueChanged_dec, _dirty_dec, _accessors_dec, _knownFields_dec, _fields_dec, _validation_dec, _errorOverrides_dec, _fieldOverrides_dec, _value_dec, _init, _value, _fieldOverrides, _errorOverrides, _validation;
336
- _value_dec = [observable.ref], _fieldOverrides_dec = [observable.shallow], _errorOverrides_dec = [observable.shallow], _validation_dec = [observable.shallow], _fields_dec = [computed], _knownFields_dec = [computed], _accessors_dec = [computed], _dirty_dec = [computed], _valueChanged_dec = [computed];
337
+ var _validateAll_dec, _validateField_dec, _setFieldValue_dec, _valueChanged_dec, _dirty_dec, _accessors_dec, _knownFields_dec, _fields_dec, _value_dec, _validation_dec, _errorOverrides_dec, _fieldOverrides_dec, _observableValue_dec, _init, _observableValue, _fieldOverrides, _errorOverrides, _validation;
338
+ _observableValue_dec = [observable.ref], _fieldOverrides_dec = [observable.shallow], _errorOverrides_dec = [observable.shallow], _validation_dec = [observable.shallow], _value_dec = [computed], _fields_dec = [computed], _knownFields_dec = [computed], _accessors_dec = [computed], _dirty_dec = [computed], _valueChanged_dec = [computed], _setFieldValue_dec = [action], _validateField_dec = [action], _validateAll_dec = [action];
337
339
  var FormModel = class {
338
340
  constructor(type, originalValue, adapters, mode) {
339
341
  this.type = type;
@@ -341,7 +343,7 @@ var FormModel = class {
341
343
  this.adapters = adapters;
342
344
  this.mode = mode;
343
345
  __runInitializers(_init, 5, this);
344
- __privateAdd(this, _value, __runInitializers(_init, 8, this)), __runInitializers(_init, 11, this);
346
+ __privateAdd(this, _observableValue, __runInitializers(_init, 8, this)), __runInitializers(_init, 11, this);
345
347
  __privateAdd(this, _fieldOverrides, __runInitializers(_init, 12, this)), __runInitializers(_init, 15, this);
346
348
  __privateAdd(this, _errorOverrides, __runInitializers(_init, 16, this, {})), __runInitializers(_init, 19, this);
347
349
  __privateAdd(this, _validation, __runInitializers(_init, 20, this, {})), __runInitializers(_init, 23, this);
@@ -352,11 +354,11 @@ var FormModel = class {
352
354
  // maintains the value paths of lists when the original order is destroyed by deletes or reordering
353
355
  __publicField(this, "listIndicesToKeys", {});
354
356
  this.originalValues = flattenValuesOfType(type, originalValue, this.listIndicesToKeys);
355
- this.value = mobxCopy(type, originalValue);
357
+ this.observableValue = mobxCopy(type, originalValue);
356
358
  this.flattenedTypeDefs = flattenTypesOfType(type);
357
359
  const conversions = flattenValueTo(
358
360
  type,
359
- this.value,
361
+ originalValue,
360
362
  () => {
361
363
  },
362
364
  (_t, fieldValue, _setter, typePath, valuePath) => {
@@ -390,6 +392,9 @@ var FormModel = class {
390
392
  throw new UnreachableError2(this.mode);
391
393
  }
392
394
  }
395
+ get value() {
396
+ return copy(this.type, this.observableValue);
397
+ }
393
398
  get fields() {
394
399
  return new Proxy(
395
400
  this.knownFields,
@@ -409,7 +414,7 @@ var FormModel = class {
409
414
  get knownFields() {
410
415
  return flattenValueTo(
411
416
  this.type,
412
- this.value,
417
+ this.observableValue,
413
418
  () => {
414
419
  },
415
420
  // TODO swap these to valuePath, typePath in flatten
@@ -451,7 +456,7 @@ var FormModel = class {
451
456
  const fieldOverride = this.fieldOverrides[valuePath];
452
457
  const accessor = this.getAccessorForValuePath(valuePath);
453
458
  const fieldTypeDef = this.flattenedTypeDefs[typePath];
454
- const context = this.toContext(this.value, valuePath);
459
+ const context = this.toContext(this.observableValue, valuePath);
455
460
  const defaultValue = create(valuePath, context);
456
461
  const {
457
462
  value,
@@ -543,9 +548,9 @@ var FormModel = class {
543
548
  get accessors() {
544
549
  return flattenAccessorsOfType(
545
550
  this.type,
546
- this.value,
551
+ this.observableValue,
547
552
  (value) => {
548
- this.value = mobxCopy(this.type, value);
553
+ this.observableValue = mobxCopy(this.type, value);
549
554
  },
550
555
  this.listIndicesToKeys
551
556
  );
@@ -567,7 +572,7 @@ var FormModel = class {
567
572
  });
568
573
  }
569
574
  get valueChanged() {
570
- return !equals(this.type, this.value, this.originalValue);
575
+ return !equals(this.type, this.observableValue, this.originalValue);
571
576
  }
572
577
  typePath(valuePath) {
573
578
  return valuePathToTypePath(this.type, valuePath, true);
@@ -592,7 +597,7 @@ var FormModel = class {
592
597
  elementTypePath,
593
598
  // TODO what can we use for the value path here?
594
599
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
595
- this.toContext(this.value, valuePath)
600
+ this.toContext(this.observableValue, valuePath)
596
601
  );
597
602
  const originalList = accessor.value;
598
603
  const newList = [
@@ -647,7 +652,7 @@ var FormModel = class {
647
652
  internalSetFieldValue(valuePath, value, validation) {
648
653
  const { revert } = this.getAdapterForValuePath(valuePath);
649
654
  assertExists(revert, "setting value not supported {}", valuePath);
650
- const conversion = revert(value, valuePath, this.toContext(this.value, valuePath));
655
+ const conversion = revert(value, valuePath, this.toContext(this.observableValue, valuePath));
651
656
  const accessor = this.getAccessorForValuePath(valuePath);
652
657
  return runInAction(() => {
653
658
  this.fieldOverrides[valuePath] = [value];
@@ -702,7 +707,7 @@ var FormModel = class {
702
707
  convert,
703
708
  create
704
709
  } = adapter2;
705
- const context = this.toContext(this.value, valuePath);
710
+ const context = this.toContext(this.observableValue, valuePath);
706
711
  const value = create(valuePath, context);
707
712
  const {
708
713
  value: displayValue
@@ -719,11 +724,11 @@ var FormModel = class {
719
724
  this.validation = {};
720
725
  this.fieldOverrides = {};
721
726
  this.errorOverrides = {};
722
- this.value = mobxCopy(this.type, value);
727
+ this.observableValue = mobxCopy(this.type, value);
723
728
  });
724
729
  }
725
730
  isValuePathActive(valuePath) {
726
- const values = flattenValuesOfType(this.type, this.value, this.listIndicesToKeys);
731
+ const values = flattenValuesOfType(this.type, this.observableValue, this.listIndicesToKeys);
727
732
  const keys = new Set(Object.keys(values));
728
733
  return keys.has(valuePath);
729
734
  }
@@ -766,18 +771,14 @@ var FormModel = class {
766
771
  return displayedValue !== originalDisplayedValue;
767
772
  }
768
773
  validateField(valuePath, validation = 2 /* Always */) {
769
- runInAction(() => {
770
- this.validation[valuePath] = validation;
771
- delete this.errorOverrides[valuePath];
772
- });
774
+ this.validation[valuePath] = validation;
775
+ delete this.errorOverrides[valuePath];
773
776
  return this.fields[valuePath].error == null;
774
777
  }
775
778
  validateAll(validation = 2 /* Always */) {
776
779
  const accessors = toArray(this.accessors);
777
- runInAction(() => {
778
- accessors.forEach(([valuePath]) => {
779
- this.validation[valuePath] = validation;
780
- });
780
+ accessors.forEach(([valuePath]) => {
781
+ this.validation[valuePath] = validation;
781
782
  });
782
783
  return accessors.every(
783
784
  ([valuePath]) => {
@@ -791,32 +792,50 @@ var FormModel = class {
791
792
  }
792
793
  };
793
794
  _init = __decoratorStart(null);
794
- _value = new WeakMap();
795
+ _observableValue = new WeakMap();
795
796
  _fieldOverrides = new WeakMap();
796
797
  _errorOverrides = new WeakMap();
797
798
  _validation = new WeakMap();
798
- __decorateElement(_init, 4, "value", _value_dec, FormModel, _value);
799
+ __decorateElement(_init, 4, "observableValue", _observableValue_dec, FormModel, _observableValue);
799
800
  __decorateElement(_init, 4, "fieldOverrides", _fieldOverrides_dec, FormModel, _fieldOverrides);
800
801
  __decorateElement(_init, 4, "errorOverrides", _errorOverrides_dec, FormModel, _errorOverrides);
801
802
  __decorateElement(_init, 4, "validation", _validation_dec, FormModel, _validation);
803
+ __decorateElement(_init, 2, "value", _value_dec, FormModel);
802
804
  __decorateElement(_init, 2, "fields", _fields_dec, FormModel);
803
805
  __decorateElement(_init, 2, "knownFields", _knownFields_dec, FormModel);
804
806
  __decorateElement(_init, 2, "accessors", _accessors_dec, FormModel);
805
807
  __decorateElement(_init, 2, "dirty", _dirty_dec, FormModel);
806
808
  __decorateElement(_init, 2, "valueChanged", _valueChanged_dec, FormModel);
809
+ __decorateElement(_init, 1, "setFieldValue", _setFieldValue_dec, FormModel);
810
+ __decorateElement(_init, 1, "validateField", _validateField_dec, FormModel);
811
+ __decorateElement(_init, 1, "validateAll", _validateAll_dec, FormModel);
807
812
  __decoratorMetadata(_init, FormModel);
808
813
 
809
814
  // core/mobx/hooks.tsx
810
815
  import {
811
816
  useCallback
812
817
  } from "react";
818
+
819
+ // core/mobx/peek.ts
820
+ import { when } from "mobx";
821
+ function peek(operation) {
822
+ let result;
823
+ void when(() => {
824
+ result = operation();
825
+ return true;
826
+ });
827
+ return result;
828
+ }
829
+
830
+ // core/mobx/hooks.tsx
813
831
  function useDefaultMobxFormHooks(model, {
814
832
  onValidFieldSubmit,
815
833
  onValidFormSubmit
816
834
  } = {}) {
817
835
  const onFieldValueChange = useCallback(
818
836
  function(path, value) {
819
- const validation = Math.min(model.getValidation(path), 1 /* Changed */);
837
+ const activeValidation = peek(() => model.getValidation(path));
838
+ const validation = Math.min(activeValidation, 1 /* Changed */);
820
839
  model.setFieldValue(path, value, validation);
821
840
  },
822
841
  [model]
@@ -836,8 +855,16 @@ function useDefaultMobxFormHooks(model, {
836
855
  const onFieldBlur = useCallback(
837
856
  function(path) {
838
857
  setTimeout(function() {
839
- if (model.isValuePathActive(path) && model.isFieldDirty(path) && model.fields[path].error == null) {
840
- model.validateField(path, Math.max(1 /* Changed */, model.getValidation(path)));
858
+ const [
859
+ validate4,
860
+ activeValidation
861
+ ] = peek(() => [
862
+ model.isValuePathActive(path) && model.isFieldDirty(path) && model.fields[path].error == null,
863
+ model.getValidation(path)
864
+ ]);
865
+ if (validate4) {
866
+ const validation = Math.max(1 /* Changed */, activeValidation);
867
+ model.validateField(path, validation);
841
868
  }
842
869
  }, 100);
843
870
  },
@@ -845,8 +872,10 @@ function useDefaultMobxFormHooks(model, {
845
872
  );
846
873
  const onFormSubmit = useCallback(
847
874
  function() {
848
- if (model.validateSubmit()) {
849
- onValidFormSubmit == null ? void 0 : onValidFormSubmit(model.value);
875
+ const valid = peek(() => model.validateSubmit());
876
+ if (valid && onValidFormSubmit) {
877
+ const value = peek(() => model.value);
878
+ onValidFormSubmit(value);
850
879
  }
851
880
  },
852
881
  [
@@ -1002,7 +1031,7 @@ var IntegerToStringConverter = class {
1002
1031
 
1003
1032
  // field_converters/NullableToBooleanConverter.ts
1004
1033
  import {
1005
- copy
1034
+ copy as copy2
1006
1035
  } from "@strictly/define";
1007
1036
  var NullableToBooleanConverter = class {
1008
1037
  constructor(typeDef, prototype, nullType, defaultToNull = true) {
@@ -1021,7 +1050,7 @@ var NullableToBooleanConverter = class {
1021
1050
  }
1022
1051
  revert(from) {
1023
1052
  if (from) {
1024
- const value = copy(this.typeDef, this.prototype);
1053
+ const value = copy2(this.typeDef, this.prototype);
1025
1054
  return {
1026
1055
  type: 0 /* Success */,
1027
1056
  value
@@ -1042,7 +1071,7 @@ import {
1042
1071
  reverse
1043
1072
  } from "@strictly/base";
1044
1073
  import {
1045
- copy as copy2
1074
+ copy as copy3
1046
1075
  } from "@strictly/define";
1047
1076
  var AbstractSelectValueTypeConverter = class {
1048
1077
  constructor(typeDef, values, defaultValueKey, noSuchValueError, required) {
@@ -1061,7 +1090,7 @@ var AbstractSelectValueTypeConverter = class {
1061
1090
  value: null
1062
1091
  };
1063
1092
  }
1064
- const value = prototype == null ? prototype : copy2(this.typeDef, prototype);
1093
+ const value = prototype == null ? prototype : copy3(this.typeDef, prototype);
1065
1094
  return {
1066
1095
  type: 0 /* Success */,
1067
1096
  value
@@ -1587,7 +1616,7 @@ function DefaultList({
1587
1616
  indexKeys[index]
1588
1617
  ];
1589
1618
  }).filter(function([
1590
- _value2,
1619
+ _value,
1591
1620
  _index,
1592
1621
  key
1593
1622
  ]) {
@@ -2029,6 +2058,7 @@ export {
2029
2058
  mergeAdaptersWithValidators,
2030
2059
  mergeFieldAdaptersWithTwoWayConverter,
2031
2060
  mergeValidators,
2061
+ peek,
2032
2062
  prototypingFieldValueFactory,
2033
2063
  subFormFieldAdapters,
2034
2064
  trimmingStringAdapter,
package/index.ts CHANGED
@@ -7,6 +7,7 @@ export * from './core/mobx/FormModel'
7
7
  export * from './core/mobx/hooks'
8
8
  export * from './core/mobx/mergeFieldAdaptersWithTwoWayConverter'
9
9
  export * from './core/mobx/mergeFieldAdaptersWithValidators'
10
+ export * from './core/mobx/peek'
10
11
  export * from './core/mobx/subFormFieldAdapters'
11
12
  export * from './core/props'
12
13
  export * from './field_converters/IntegerToStringConverter'
package/package.json CHANGED
@@ -72,7 +72,7 @@
72
72
  "test:watch": "vitest"
73
73
  },
74
74
  "type": "module",
75
- "version": "0.0.31",
75
+ "version": "0.0.32",
76
76
  "exports": {
77
77
  ".": {
78
78
  "import": {