@paragrav/rhf-utils 0.0.120 → 0.0.121

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/README.md CHANGED
@@ -18,7 +18,7 @@ To configure, create a file `config.tsx` with desired configuration settings. Th
18
18
 
19
19
  ```tsx
20
20
  export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
21
- // overridable per form instance
21
+ // overridable at individual form level
22
22
  defaults: {
23
23
  // globally-relevant subset of RHF's `UseFormProps` options
24
24
  rhf: {
@@ -43,7 +43,6 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
43
43
 
44
44
  // optional wrapper to inject your own hooks and components
45
45
  // around all RhfUtilsZodForm instances
46
- // (see further below for more info)
47
46
  FormChildren: (
48
47
  // UseRhfUtilsFormChildrenProps
49
48
  {
@@ -56,7 +55,8 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
56
55
  children, // RhfUtilsZodForm's Children instance
57
56
  },
58
57
  ) => {
59
- // your navigation blocker (using custom option prop -- see "Extend RhfUtilsFormOptions" section)
58
+ // your own hooks/behaviors
59
+ // (using custom option prop -- see "Extend RhfUtilsFormOptions" section)
60
60
  useMyFormNavigationPrompt(!!options?.enableMyFormNavigationPrompt);
61
61
 
62
62
  return (
@@ -82,15 +82,22 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
82
82
  return transformServerErrorToFormSubmitErrors(error);
83
83
  },
84
84
 
85
- errors: {
85
+ // form state field errors
86
+ fieldErrors: {
87
+ // callbacks to determine when to output information about field errors
88
+ // provided `FlatFieldErrorsContext` (all, fields, roots, orphans, hasOrphans)
86
89
  output: {
87
- // callback to determine when to output form context errors to console ("debug" or "error")
90
+ // determine when to console ("debug" or "error")
88
91
  console: ({ hasOrphans }) =>
89
- (hasOrphans && { type: 'error' }) || // console error for reporting on prod
90
- (import.meta.env.DEV && { type: 'debug' }), // facilitate debugging on dev
91
-
92
- // callback to determine when to throw an error based on context
93
- throw: ({ hasOrphans }) => import.meta.env.DEV && hasOrphans,
92
+ // console error for reporting on prod
93
+ (hasOrphans && { type: 'error' }) ||
94
+ // facilitate local debugging of form validation
95
+ (import.meta.env.DEV && { type: 'debug' }),
96
+
97
+ // callback to determine when to throw an error based on field errors
98
+ throw: ({ hasOrphans }) =>
99
+ // bring attention to orphans locally
100
+ import.meta.env.DEV && hasOrphans,
94
101
  },
95
102
  },
96
103
  };
@@ -122,7 +129,7 @@ Currently, only `zod` is supported.
122
129
  context, // UseRhfUtilsFormOnSubmitContext (id, ref, rhf context, utils options, strictly-typed FormSubmitError class)
123
130
  event, // SubmitEvent
124
131
  ) => {
125
- await authLoginService(data);
132
+ await loginService(data);
126
133
  props.onSuccess();
127
134
  }}
128
135
  // handle error declaratively (i.e., no throw/catch)
@@ -150,6 +157,7 @@ Currently, only `zod` is supported.
150
157
  <label>
151
158
  Email
152
159
  <input {...field} disabled={isSubmitting} />
160
+ <FormErrorMessageByPath path={field.name} />
153
161
  </label>
154
162
  )}
155
163
  />
@@ -157,14 +165,16 @@ Currently, only `zod` is supported.
157
165
  <button type="submit">Login</button>
158
166
  </>
159
167
  )}
160
- // options/overrides
168
+ // form-specific options/overrides
161
169
  rhf={{
162
170
  mode: 'onBlur',
163
171
  }}
164
172
  utils={{
165
173
  submitOnChange: true,
166
174
  resetValuesOnSubmitError: true,
167
- enableMyFormNavigationPrompt: true, // custom option prop (see "Extend RhfUtilsFormOptions" section)
175
+ // custom option props
176
+ // (see "Extend RhfUtilsFormOptions" section)
177
+ enableMyFormNavigationPrompt: true,
168
178
  }}
169
179
  form={{
170
180
  // class names are merged together with global defaults
@@ -173,7 +183,17 @@ Currently, only `zod` is supported.
173
183
  />
174
184
  ```
175
185
 
176
- `Children` is a component which is rendered as a child of the form. It receives `UseRhfUtilsFormChildrenProps` as props, including type-safe `Controller`.
186
+ `Children` prop takes a component which is rendered as a child of the form (and, if supplied, of `RhfUtilsClientConfig.FormChildren`). It receives `UseRhfUtilsFormChildrenProps` as props, including a type-safe `Controller` component.
187
+
188
+ The component hierarchy is:
189
+
190
+ ```tsx
191
+ <RhfUtilsClientConfig.FormComponent>
192
+ <RhfUtilsClientConfig.FormChildren>
193
+ <RhfUtilsZodForm.Children />
194
+ </RhfUtilsClientConfig.FormChildren>
195
+ </RhfUtilsClientConfig.FormComponent>
196
+ ```
177
197
 
178
198
  If you prefer to define your `Children` component as standalone:
179
199
 
@@ -234,11 +254,11 @@ type RhfUtilsFormOptions = {
234
254
 
235
255
  If you need access to options deeper in component structure, use `useRhfUtilsContext` to receive `RhfUtilsContext` object, which includes `formId`, `formRef`, and `options` settings.
236
256
 
237
- Use `useRhfUtilsContextRequestSubmit` to get `requestSubmit` fn for current form ref in context. This is useful when you need to trigger form submission programatically.
257
+ Use `useRhfUtilsContextRequestSubmit` hook to get `requestSubmit` function for current form ref in context. This is useful when you need to trigger form submission programatically.
238
258
 
239
259
  ## Extend `RhfUtilsFormOptions`
240
260
 
241
- Extend `RhfUtilsFormOptions` with custom options, which get passed to `Children` component in `options` prop.
261
+ Extend `RhfUtilsFormOptions` with custom options, which get passed to `Children` component in `options` prop. These can take any shape, and allow you to override your own functionality at form-level.
242
262
 
243
263
  ```tsx
244
264
  import '@paragrav/rhf-utils';
@@ -257,7 +277,7 @@ declare module '@paragrav/rhf-utils' {
257
277
 
258
278
  You can configure via `RhfUtilsClientConfig` (example at the top) when form context errors are outputted -- i.e., via console and/or thrown error.
259
279
 
260
- Use `useFlatFieldErrorsContext()` hook, which returns an object with errors grouped by `all`, `fields`, `root`, and `orphans`.
280
+ Use `useFlatFieldErrorsContext()` hook, which returns an object with errors grouped by `all`, `fields`, `roots`, `orphans` records, and `hasErrors` and `hasErrors` and `hasOrphans` booleans.
261
281
 
262
282
  ### Orphans
263
283
 
@@ -269,7 +289,7 @@ The criteria for an orphan is any form context error that meets all of the follo
269
289
  - has no `ref` -- RHF includes `ref` to the associated input on each error object (when applicable)
270
290
  - has no marker in DOM (e.g., `FormNonFieldErrorMarker`)
271
291
 
272
- To get accurate orphan analysis, you must either use `FormNonFieldErrorMarker` in any error you are displaying to user which is not "root" and doesn't have a `ref`. (There is no harm in using this consistently across all errors, even those expected to have a ref.)
292
+ To get accurate orphan analysis, you must either use `FormNonFieldErrorMarker` in any error you are displaying to user that is not "root" and doesn't have a `ref`. (There is no harm in using this consistently across all errors, even those expected to have a ref.)
273
293
 
274
294
  Alternatively, you can use `FormErrorMessageByPath` to display error message to user:
275
295
 
@@ -277,12 +297,12 @@ Alternatively, you can use `FormErrorMessageByPath` to display error message to
277
297
  <FormErrorMessageByPath path="street.address" />
278
298
  ```
279
299
 
280
- Example use case: Field array with minimum items. (When there are no items, the error is not associated with a field and is displayed separately.)
300
+ Example use case: Field array with minimum items. When there are no items, the error is not associated with a field and is displayed separately.
281
301
 
282
302
  Orphans are exposed in a few places.
283
303
 
284
304
  - In errors outputted via console. (Configurable via `RhfUtilsClientConfig['errors']['output']`.)
285
- - And `useFlatFieldErrorsContext()` hook, which returns an object with errors grouped by `all`, `fields`, `root`, and `orphans`.
305
+ - And `useFlatFieldErrorsContext()` hook, which returns an object with errors grouped by `all`, `fields`, `roots`, `orphans` records, and `hasErrors` and `hasOrphans` boolean.
286
306
  - Boolean value from `useFlatFieldErrorsContextHasOnlyOrphans`.
287
307
 
288
308
  `FlatFieldErrors` is a flattened, simplified version of RHF's `FieldErrors`. Keys represent field paths flattened to dot notation.
@@ -1,23 +1,27 @@
1
- import { jsx as s } from "react/jsx-runtime";
1
+ import { jsx as a } from "react/jsx-runtime";
2
2
  import "react";
3
- import { useFormState as i } from "react-hook-form";
4
- import l from "../../getRefdFromFlatFieldErrors.mjs";
5
- import F from "../../orphan/getOrphansFromFlatFieldErrors.mjs";
6
- import a from "../../root/getRootsFromFlatFieldErrors.mjs";
7
- import n from "../getFlatFieldErrors.mjs";
8
- import { _FormErrorsFlatContextProvider as p } from "./useFlatFieldErrorsContext.mjs";
9
- const h = ({
3
+ import { useFormState as l } from "react-hook-form";
4
+ import F from "../../getRefdFromFlatFieldErrors.mjs";
5
+ import e from "../../../utils/isEmptyObject.mjs";
6
+ import p from "../../orphan/getOrphansFromFlatFieldErrors.mjs";
7
+ import n from "../../root/getRootsFromFlatFieldErrors.mjs";
8
+ import d from "../getFlatFieldErrors.mjs";
9
+ import { _FormErrorsFlatContextProvider as f } from "./useFlatFieldErrorsContext.mjs";
10
+ const C = ({
10
11
  formRef: o,
11
- children: t
12
+ children: m
12
13
  }) => {
13
- const { errors: e } = i(), r = n(e), m = {
14
+ const { errors: t } = l(), r = d(t), s = o.current ? p(r, o.current) : {}, i = {
14
15
  all: r,
15
- fields: l(r),
16
- roots: a(r),
17
- orphans: o.current ? F(r, o.current) : {}
16
+ fields: F(r),
17
+ roots: n(r),
18
+ orphans: s,
19
+ // computed
20
+ hasErrors: !e(t),
21
+ hasOrphans: e(s)
18
22
  };
19
- return /* @__PURE__ */ s(p, { value: m, children: t });
23
+ return /* @__PURE__ */ a(f, { value: i, children: m });
20
24
  };
21
25
  export {
22
- h as default
26
+ C as default
23
27
  };
@@ -1,10 +1,9 @@
1
- import t from "react";
2
- import s from "../../../utils/isEmptyObject.mjs";
1
+ import s from "react";
3
2
  import e from "./useFlatFieldErrorsContext.mjs";
4
- const n = () => {
3
+ const t = () => {
5
4
  const r = e();
6
- return t.useMemo(() => s(r.orphans) ? !1 : Object.keys(r.orphans).length === Object.keys(r.all).length, [r]);
7
- }, O = n;
5
+ return s.useMemo(() => !r.hasErrors || !r.hasOrphans ? !1 : Object.keys(r.orphans).length === Object.keys(r.all).length, [r]);
6
+ }, l = t;
8
7
  export {
9
- O as default
8
+ l as default
10
9
  };
@@ -1,28 +1,25 @@
1
- import h from "react";
2
- import { useFormContext as E } from "react-hook-form";
3
- import l from "../../../utils/isEmptyObject.mjs";
4
- import F from "../../output/consoleErrors.mjs";
5
- import x from "./useFlatFieldErrorsContext.mjs";
6
- const n = (r) => {
7
- const u = E(), t = x();
8
- h.useEffect(() => {
9
- var m, a;
10
- if (l(t.all))
1
+ import u from "react";
2
+ import { useFormContext as p } from "react-hook-form";
3
+ import E from "../../output/consoleErrors.mjs";
4
+ import F from "./useFlatFieldErrorsContext.mjs";
5
+ const C = (r) => {
6
+ const l = p(), t = F();
7
+ u.useEffect(() => {
8
+ var o, m;
9
+ if (!t.hasErrors)
11
10
  return;
12
- const o = {
13
- hasOrphans: !l(t.orphans)
14
- }, e = (m = r == null ? void 0 : r.console) == null ? void 0 : m.call(r, o);
15
- e && F(
16
- e.message ?? p,
17
- u.getValues(),
11
+ const e = (o = r == null ? void 0 : r.console) == null ? void 0 : o.call(r, t);
12
+ e && E(
13
+ e.message ?? a,
14
+ l.getValues(),
18
15
  t,
19
16
  e.type
20
17
  );
21
- const s = (a = r == null ? void 0 : r.throw) == null ? void 0 : a.call(r, o);
18
+ const s = (m = r == null ? void 0 : r.throw) == null ? void 0 : m.call(r, t);
22
19
  if (s)
23
- throw new Error(typeof s == "string" ? s : p);
20
+ throw new Error(typeof s == "string" ? s : a);
24
21
  }, [t]);
25
- }, p = "Form errors";
22
+ }, a = "Form errors";
26
23
  export {
27
- n as default
24
+ C as default
28
25
  };
@@ -1,82 +1,78 @@
1
- import { jsx as a, jsxs as v, Fragment as E } from "react/jsx-runtime";
1
+ import { jsx as s, jsxs as j } from "react/jsx-runtime";
2
2
  import "react";
3
- import { useFormContext as P } from "react-hook-form";
3
+ import { useFormContext as v } from "react-hook-form";
4
4
  import w from "../client/config/useRhfUtilsClientConfigContext.mjs";
5
- import S from "../devtool/LazyDevTool.mjs";
6
- import { FormSubmitError as h } from "../submit/error/FormSubmitError.mjs";
7
- import U from "../submit/error/setCtxErrorsByFormSubmitErrors.mjs";
5
+ import E from "../devtool/LazyDevTool.mjs";
6
+ import { FormSubmitError as c } from "../submit/error/FormSubmitError.mjs";
7
+ import S from "../submit/error/setCtxErrorsByFormSubmitErrors.mjs";
8
+ import U from "../utils/PassthroughChildren.mjs";
8
9
  import _ from "./_Controller.mjs";
9
10
  function G({
10
- formId: n,
11
- formRef: p,
11
+ formId: p,
12
+ formRef: m,
12
13
  //
13
- onSubmit: c,
14
- onSubmitError: d,
15
- onSubmitInvalid: F,
16
- Children: i,
14
+ onSubmit: a,
15
+ onSubmitError: h,
16
+ onSubmitInvalid: i,
17
+ Children: l,
17
18
  //
18
- form: l,
19
+ form: F,
19
20
  utils: o
20
21
  }) {
21
- const e = P(), r = w(), y = async (t) => {
22
+ const n = v(), r = w(), y = async (t) => {
22
23
  o != null && o.stopSubmitPropagation && t.stopPropagation();
23
24
  try {
24
- await e.handleSubmit(f, F)(t);
25
- } catch (m) {
26
- b(m, t);
25
+ await n.handleSubmit(f, i)(t);
26
+ } catch (e) {
27
+ b(e, t);
27
28
  }
28
- }, f = (t, m) => c == null ? void 0 : c(
29
+ }, f = (t, e) => a == null ? void 0 : a(
29
30
  t,
30
31
  {
31
- formId: n,
32
- formRef: p,
33
- context: e,
32
+ formId: p,
33
+ formRef: m,
34
+ context: n,
34
35
  utils: o,
35
- FormSubmitError: h
36
+ FormSubmitError: c
36
37
  },
37
- m
38
- ), b = (t, m) => {
38
+ e
39
+ ), b = (t, e) => {
39
40
  var x;
40
- const C = t instanceof h ? (
41
+ const C = t instanceof c ? (
41
42
  // consumer can manually throw FormSubmitError (e.g., manual validation)
42
43
  t.errors
43
44
  ) : (
44
45
  // if error is not FormSubmitError, consumer can provide global handler
45
46
  (x = r == null ? void 0 : r.onSubmitUnknownError) == null ? void 0 : x.call(r, t)
46
47
  );
47
- C && U(e, C), d == null || d(
48
+ C && S(n, C), h == null || h(
48
49
  t,
49
50
  {
50
- formId: n,
51
- formRef: p,
52
- context: e,
51
+ formId: p,
52
+ formRef: m,
53
+ context: n,
53
54
  utils: o
54
55
  },
55
- m
56
+ e
56
57
  );
57
- }, s = {
58
- formId: n,
59
- formRef: p,
60
- context: e,
58
+ }, d = {
59
+ formId: p,
60
+ formRef: m,
61
+ context: n,
61
62
  utils: o,
62
63
  Controller: _,
63
- FormSubmitError: h
64
- }, T = (r == null ? void 0 : r.FormComponent) ?? "form", j = (r == null ? void 0 : r.FormChildren) ?? k;
65
- return /* @__PURE__ */ a(T, { ...l, ref: p, onSubmit: y, children: /* @__PURE__ */ v(j, { ...s, children: [
66
- (o == null ? void 0 : o.devTool) && /* @__PURE__ */ a(
67
- S,
64
+ FormSubmitError: c
65
+ }, P = (r == null ? void 0 : r.FormComponent) ?? "form", T = (r == null ? void 0 : r.FormChildren) ?? U;
66
+ return /* @__PURE__ */ s(P, { ...F, ref: m, onSubmit: y, children: /* @__PURE__ */ j(T, { ...d, children: [
67
+ (o == null ? void 0 : o.devTool) && /* @__PURE__ */ s(
68
+ E,
68
69
  {
69
70
  props: typeof o.devTool == "object" ? o.devTool : void 0
70
71
  }
71
72
  ),
72
- /* @__PURE__ */ a(i, { ...s })
73
+ /* @__PURE__ */ s(l, { ...d })
73
74
  ] }) });
74
75
  }
75
- function k({
76
- children: n
77
- }) {
78
- return /* @__PURE__ */ a(E, { children: n });
79
- }
80
76
  export {
81
77
  G as default
82
78
  };
@@ -4,18 +4,18 @@ import F from "../../../errors/flat/context/useFlatFieldErrorsContextOutput.mjs"
4
4
  import x from "../../../submit/useFormOnSubmitSuccessfulAndReset.mjs";
5
5
  import O from "../../../submit/useResetFormOnSubmitError.mjs";
6
6
  import b from "../../../submit/useResetFormOnSubmitSuccessful.mjs";
7
- import h from "../../../submit/useSubmitFormOnChange.mjs";
8
- import { _RhfUtilsContextProvider as d } from "./useRhfUtilsContext.mjs";
7
+ import d from "../../../submit/useSubmitFormOnChange.mjs";
8
+ import { _RhfUtilsContextProvider as h } from "./useRhfUtilsContext.mjs";
9
9
  const M = ({
10
- formId: a,
10
+ formId: f,
11
11
  formRef: t,
12
12
  onSubmitSuccessfulAndReset: e,
13
13
  options: r,
14
- children: f
14
+ children: a
15
15
  }) => {
16
16
  var u;
17
17
  const m = C();
18
- return F((u = m == null ? void 0 : m.errors) == null ? void 0 : u.output), h(t, {
18
+ return F((u = m == null ? void 0 : m.fieldErrors) == null ? void 0 : u.output), d(t, {
19
19
  disabled: !(r != null && r.submitOnChange)
20
20
  }), O({
21
21
  disabled: !(r != null && r.resetValuesOnSubmitError)
@@ -23,7 +23,7 @@ const M = ({
23
23
  (r == null ? void 0 : r.resetFormAfterSubmitSuccessful) || !!e
24
24
  ), x(() => {
25
25
  e == null || e();
26
- }), /* @__PURE__ */ l(d, { value: { formId: a, formRef: t, options: r }, children: f });
26
+ }), /* @__PURE__ */ l(h, { value: { formId: f, formRef: t, options: r }, children: a });
27
27
  };
28
28
  export {
29
29
  M as default
@@ -0,0 +1,7 @@
1
+ import { jsx as t, Fragment as o } from "react/jsx-runtime";
2
+ const a = ({
3
+ children: r
4
+ }) => /* @__PURE__ */ t(o, { children: r });
5
+ export {
6
+ a as default
7
+ };
@@ -57,7 +57,7 @@ export type RhfUtilsClientConfig = {
57
57
  * - if `undefined`: do nothing.
58
58
  */
59
59
  onSubmitUnknownError?: (error: unknown) => FormSubmitErrors | undefined;
60
- errors?: {
60
+ fieldErrors?: {
61
61
  /**
62
62
  * Configure how/if errors should be outputted.
63
63
  */
@@ -1,4 +1,5 @@
1
- import { RhfUtilsErrorsOutputConfigContext, RhfUtilsErrorsOutputConsoleConfig } from '../../output/types';
1
+ import { RhfUtilsErrorsOutputConsoleConfig } from '../../output/types';
2
+ import { FlatFieldErrorsContext } from './useFlatFieldErrorsContext';
2
3
 
3
4
  export type FlatFieldErrorsOutputConfig = {
4
5
  /**
@@ -8,12 +9,12 @@ export type FlatFieldErrorsOutputConfig = {
8
9
  * - console.debug errors in development environment.
9
10
  * - console.error certain errors in production environment.
10
11
  */
11
- console?: (context: RhfUtilsErrorsOutputConfigContext) => RhfUtilsErrorsOutputConsoleConfig | null | false | undefined;
12
+ console?: (context: FlatFieldErrorsContext) => RhfUtilsErrorsOutputConsoleConfig | null | false | undefined;
12
13
  /**
13
14
  * Configure how/if errors should be thrown.
14
15
  *
15
16
  * Example use case:
16
17
  * - bring attention to certain errors in development environment.
17
18
  */
18
- throw?: (context: RhfUtilsErrorsOutputConfigContext) => true | string | false | undefined;
19
+ throw?: (context: FlatFieldErrorsContext) => true | string | false | undefined;
19
20
  };
@@ -5,6 +5,8 @@ export type FlatFieldErrorsContext = {
5
5
  fields: FlatFieldErrors;
6
6
  roots: FlatFieldErrors;
7
7
  orphans: FlatFieldErrors;
8
+ hasErrors: boolean;
9
+ hasOrphans: boolean;
8
10
  };
9
11
  declare const _FormErrorsFlatContextProvider: import('react').Provider<FlatFieldErrorsContext | undefined>, useFlatFieldErrorsContext: () => FlatFieldErrorsContext;
10
12
  export default useFlatFieldErrorsContext;
@@ -1,8 +1,7 @@
1
- import { FieldErrors } from 'react-hook-form';
2
1
  import { SafeFieldValues } from '../../form/SafeFieldValues';
3
2
 
4
3
  /**
5
4
  * Output form values and errors to console.
6
5
  */
7
- declare const consoleErrors: (message: string, values: SafeFieldValues, errors: FieldErrors, type?: 'debug' | 'error') => void;
6
+ declare const consoleErrors: (message: string, values: SafeFieldValues, errors: Record<string, unknown>, type?: 'debug' | 'error') => void;
8
7
  export default consoleErrors;
@@ -5,10 +5,3 @@ export type RhfUtilsErrorsOutputConsoleConfig = {
5
5
  type?: 'debug' | 'error';
6
6
  message?: string;
7
7
  };
8
- /**
9
- * Contextual data to determine whether to output error.
10
- */
11
- export type RhfUtilsErrorsOutputConfigContext = {
12
- isDevelopment?: boolean;
13
- hasOrphans?: boolean;
14
- };
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ /**
3
+ * Component for simply passing through children.
4
+ *
5
+ * (Useful for conditional wrapping of children.)
6
+ */
7
+ declare const PassthroughChildren: React.FC<React.PropsWithChildren>;
8
+ export default PassthroughChildren;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@paragrav/rhf-utils",
3
3
  "author": "paragrav.dev",
4
4
  "license": "MIT",
5
- "version": "0.0.120",
5
+ "version": "0.0.121",
6
6
  "description": "Integration utilities for react-hook-form.",
7
7
  "type": "module",
8
8
  "sideEffects": false,