@fougere/nuxt 0.16.0-alpha.0 → 0.16.3-alpha.0

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.
@@ -1,4 +1,4 @@
1
- import { type FormEntity, type FormField } from '@fougere/app/client';
1
+ import { type FormEntity, type FormField, type FormErrors, type FormFieldName, type FormRow, type FormValues } from '@fougere/app/client';
2
2
  export interface FormOptions {
3
3
  /** Command the submit rides. Default: 'create'. */
4
4
  op?: string;
@@ -7,16 +7,16 @@ export interface FormOptions {
7
7
  /** Call params designating the target (edit mode: { id }). */
8
8
  params?: Record<string, string>;
9
9
  }
10
- export declare function useFormFor<T = Record<string, unknown>>(entity: FormEntity, options?: FormOptions): {
11
- fields: FormField[];
10
+ export declare function useFormFor<E extends FormEntity>(entity: E, options?: FormOptions): {
11
+ fields: FormField<FormFieldName<E>>[];
12
12
  /**
13
13
  * The same fields, keyed by name — a form that lays its inputs out by hand binds one at a time
14
14
  * (`v-bind="fieldsByName.email.attrs"`), and still states no rule of its own.
15
15
  */
16
- fieldsByName: Record<string, FormField>;
17
- values: Record<string, unknown>;
18
- errors: Record<string, string>;
19
- submit: () => Promise<T | null>;
16
+ fieldsByName: Partial<Record<FormFieldName<E>, FormField<FormFieldName<E>>>>;
17
+ values: FormValues<E>;
18
+ errors: FormErrors<E>;
19
+ submit: () => Promise<FormRow<E> | null>;
20
20
  loading: import("vue").Ref<boolean, boolean>;
21
21
  /** Non-validation failure of the last submit (unreachable host, conflict…). */
22
22
  error: import("vue").Ref<import("@fougere/core/contract").FougereError<import("@fougere/core/contract").ErrorCode> | null, import("@fougere/core/contract").FougereError<import("@fougere/core/contract").ErrorCode> | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"useFormFor.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/useFormFor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoD,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAExH,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,wBAAgB,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE,WAAgB;;IAgDjG;;;OAGG;kBACiE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;;;kBArBtE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;;IA0BxC,+EAA+E;;;EAIlF"}
1
+ {"version":3,"file":"useFormFor.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/useFormFor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoD,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE5L,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,GAAE,WAAgB;;IA0CjF;;;OAGG;kBACiE,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAChH,UAAU,CAAC,CAAC,CAAC;YACb,UAAU,CAAC,CAAC,CAAC;kBAjBR,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;;IAoBjD,+EAA+E;;;EAIlF"}
@@ -13,7 +13,7 @@ export function useFormFor(entity, options = {}) {
13
13
  const values = reactive(Object.fromEntries(fields.map((f) => [f.name, options.initial?.[f.name] ?? f.default])));
14
14
  const errors = reactive({});
15
15
  // A form is designated by its ENTITY — it is a set of fields — so the facade it submits to is
16
- // an address with no handler type behind it, and `T` stays the caller's to state.
16
+ // an address with no handler type behind it, and what it answers is the entity's row.
17
17
  const command = useCommand(facadeOf(entity), options.op ?? 'create');
18
18
  function clearErrors() {
19
19
  for (const key of Object.keys(errors))
@@ -32,17 +32,11 @@ export function useFormFor(entity, options = {}) {
32
32
  async function submit() {
33
33
  if (!validator())
34
34
  return null;
35
- try {
36
- return (await command.execute({ params: options.params, input: payloadOf(entity, values) }));
37
- }
38
- catch (err) {
39
- const refusals = validationErrorsOf(err);
40
- if (refusals) {
41
- Object.assign(errors, errorsByField(refusals));
42
- return null;
43
- }
44
- throw err;
45
- }
35
+ const answer = await command.execute({ params: options.params, input: payloadOf(entity, values) });
36
+ const refusals = command.error.value && validationErrorsOf(command.error.value);
37
+ if (refusals)
38
+ Object.assign(errors, errorsByField(refusals));
39
+ return answer;
46
40
  }
47
41
  return {
48
42
  fields,
@@ -51,8 +45,8 @@ export function useFormFor(entity, options = {}) {
51
45
  * (`v-bind="fieldsByName.email.attrs"`), and still states no rule of its own.
52
46
  */
53
47
  fieldsByName: Object.fromEntries(fields.map((f) => [f.name, f])),
54
- values,
55
- errors,
48
+ values: values,
49
+ errors: errors,
56
50
  submit,
57
51
  loading: command.loading,
58
52
  /** Non-validation failure of the last submit (unreachable host, conflict…). */
@@ -1 +1 @@
1
- {"version":3,"file":"useFormFor.js","sourceRoot":"","sources":["../../../src/runtime/composables/useFormFor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useFormFor.js","sourceRoot":"","sources":["../../../src/runtime/composables/useFormFor.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ export declare function useQuery<Handler, Address extends string, Op extends key
14
14
  refresh: () => Promise<void>;
15
15
  }>;
16
16
  export declare function useCommand<Handler, Address extends string, Op extends keyof Handler & string>(facade: FacadeName<Handler, Address>, op: Op): {
17
- execute: (input?: CallInput) => Promise<Answer<Handler, Op>>;
17
+ execute: (input?: CallInput) => Promise<Answer<Handler, Op> | null>;
18
18
  loading: Ref<boolean, boolean>;
19
19
  error: Ref<FougereError<Refused<Address, Op>> | null, FougereError<Refused<Address, Op>> | null>;
20
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useFougereData.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/useFougereData.ts"],"names":[],"mappings":"AAKA,OAAO,EAA0C,KAAK,gBAAgB,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAC9F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAWL,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,IAAI,EAEV,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,wBAAsB,QAAQ,CAC5B,OAAO,EACP,OAAO,SAAS,MAAM,EACtB,EAAE,SAAS,MAAM,OAAO,GAAG,MAAM,EAEjC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,EACpC,EAAE,EAAE,EAAE,EACN,KAAK,CAAC,EAAE,gBAAgB,CAAC,SAAS,GAAG,SAAS,CAAC,EAC/C,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE;UA2Bd,GAAG,CAAC,sBAAW,IAAI,CAAC;;;;;;aAQd,MAAM,OAAO,CAAC,IAAI,CAAC;GAE1C;AAED,wBAAgB,UAAU,CACxB,OAAO,EACP,OAAO,SAAS,MAAM,EACtB,EAAE,SAAS,MAAM,OAAO,GAAG,MAAM,EACjC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE;sBAQb,SAAS,KAAG,OAAO,qBAAU;;;EAmB7D"}
1
+ {"version":3,"file":"useFougereData.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/useFougereData.ts"],"names":[],"mappings":"AAKA,OAAO,EAA0C,KAAK,gBAAgB,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAC9F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAWL,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,IAAI,EAEV,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,wBAAsB,QAAQ,CAC5B,OAAO,EACP,OAAO,SAAS,MAAM,EACtB,EAAE,SAAS,MAAM,OAAO,GAAG,MAAM,EAEjC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,EACpC,EAAE,EAAE,EAAE,EACN,KAAK,CAAC,EAAE,gBAAgB,CAAC,SAAS,GAAG,SAAS,CAAC,EAC/C,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE;UA2Bd,GAAG,CAAC,sBAAW,IAAI,CAAC;;;;;;aAQd,MAAM,OAAO,CAAC,IAAI,CAAC;GAE1C;AAED,wBAAgB,UAAU,CACxB,OAAO,EACP,OAAO,SAAS,MAAM,EACtB,EAAE,SAAS,MAAM,OAAO,GAAG,MAAM,EACjC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE;sBASb,SAAS,KAAG,OAAO,CAAC,sBAAW,IAAI,CAAC;;;EAoBpE"}
@@ -39,6 +39,7 @@ export function useCommand(facade, op) {
39
39
  const fetcher = useRequestFetch();
40
40
  const loading = ref(false);
41
41
  const error = ref(null);
42
+ /** The answer, or `null` when the call was refused — the refusal is in `error`, and nothing is thrown. */
42
43
  async function execute(input) {
43
44
  loading.value = true;
44
45
  error.value = null;
@@ -52,7 +53,7 @@ export function useCommand(facade, op) {
52
53
  }
53
54
  catch (err) {
54
55
  error.value = asFougereError(err, entityKey, op);
55
- throw error.value;
56
+ return null;
56
57
  }
57
58
  finally {
58
59
  loading.value = false;
@@ -1 +1 @@
1
- {"version":3,"file":"useFougereData.js","sourceRoot":"","sources":["../../../src/runtime/composables/useFougereData.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useFougereData.js","sourceRoot":"","sources":["../../../src/runtime/composables/useFougereData.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fougere/nuxt",
3
- "version": "0.16.0-alpha.0",
3
+ "version": "0.16.3-alpha.0",
4
4
  "description": "The Nuxt module: Fougere's client primitives and server surface.",
5
5
  "keywords": [
6
6
  "fougere",
@@ -32,12 +32,12 @@
32
32
  "template"
33
33
  ],
34
34
  "dependencies": {
35
- "@fougere/app": "0.16.0-alpha.0",
36
- "@fougere/core": "0.16.0-alpha.0",
37
- "@fougere/defaults": "0.16.0-alpha.0",
35
+ "@fougere/app": "0.16.3-alpha.0",
36
+ "@fougere/core": "0.16.3-alpha.0",
37
+ "@fougere/defaults": "0.16.3-alpha.0",
38
38
  "@nuxt/kit": "^4.5.1",
39
39
  "jiti": "^2.6.1",
40
- "@fougere/compiler": "0.16.0-alpha.0"
40
+ "@fougere/compiler": "0.16.3-alpha.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@nuxt/schema": "^4.5.1",
@@ -2,7 +2,7 @@
2
2
  import { reactive, computed } from 'vue';
3
3
  import { lowerFirst, validationErrorsOf } from '@fougere/core/contract';
4
4
  import { useCommand } from './useFougereData.js';
5
- import { facadeOf, formFieldsOf, payloadOf, errorsByField, type FormEntity, type FormField } from '@fougere/app/client';
5
+ import { facadeOf, formFieldsOf, payloadOf, errorsByField, type FormEntity, type FormField, type FormErrors, type FormFieldName, type FormRow, type FormValues } from '@fougere/app/client';
6
6
 
7
7
  export interface FormOptions {
8
8
  /** Command the submit rides. Default: 'create'. */
@@ -13,9 +13,9 @@ export interface FormOptions {
13
13
  params?: Record<string, string>;
14
14
  }
15
15
 
16
- export function useFormFor<T = Record<string, unknown>>(entity: FormEntity, options: FormOptions = {}) {
16
+ export function useFormFor<E extends FormEntity>(entity: E, options: FormOptions = {}) {
17
17
  const entityKey = lowerFirst(entity.name);
18
- const fields: FormField[] = formFieldsOf(entity, entityKey);
18
+ const fields = formFieldsOf(entity, entityKey);
19
19
 
20
20
  // `initial` wins over the declared default: editing a row shows the row, including a
21
21
  // value the author deliberately changed away from that default. On a create form
@@ -26,7 +26,7 @@ export function useFormFor<T = Record<string, unknown>>(entity: FormEntity, opti
26
26
  );
27
27
  const errors = reactive<Record<string, string>>({});
28
28
  // A form is designated by its ENTITY — it is a set of fields — so the facade it submits to is
29
- // an address with no handler type behind it, and `T` stays the caller's to state.
29
+ // an address with no handler type behind it, and what it answers is the entity's row.
30
30
  const command = useCommand(facadeOf(entity), options.op ?? 'create');
31
31
 
32
32
  function clearErrors() {
@@ -38,25 +38,19 @@ export function useFormFor<T = Record<string, unknown>>(entity: FormEntity, opti
38
38
  clearErrors();
39
39
  const result = entity.validate(payloadOf(entity, values));
40
40
  if (result.success) return true;
41
- Object.assign(errors, errorsByField(result.errors));
41
+ Object.assign(errors, errorsByField<E>(result.errors));
42
42
 
43
43
  return false;
44
44
  }
45
45
 
46
46
  /** Validate locally, then send through the command. */
47
- async function submit(): Promise<T | null> {
47
+ async function submit(): Promise<FormRow<E> | null> {
48
48
  if (!validator()) return null;
49
- try {
50
- return (await command.execute({ params: options.params, input: payloadOf(entity, values) })) as T;
51
- } catch (err) {
52
- const refusals = validationErrorsOf(err);
53
- if (refusals) {
54
- Object.assign(errors, errorsByField(refusals));
49
+ const answer = await command.execute({ params: options.params, input: payloadOf(entity, values) });
50
+ const refusals = command.error.value && validationErrorsOf(command.error.value);
51
+ if (refusals) Object.assign(errors, errorsByField<E>(refusals));
55
52
 
56
- return null;
57
- }
58
- throw err;
59
- }
53
+ return answer as FormRow<E> | null;
60
54
  }
61
55
 
62
56
  return {
@@ -65,9 +59,9 @@ export function useFormFor<T = Record<string, unknown>>(entity: FormEntity, opti
65
59
  * The same fields, keyed by name — a form that lays its inputs out by hand binds one at a time
66
60
  * (`v-bind="fieldsByName.email.attrs"`), and still states no rule of its own.
67
61
  */
68
- fieldsByName: Object.fromEntries(fields.map((f) => [f.name, f])) as Record<string, FormField>,
69
- values,
70
- errors,
62
+ fieldsByName: Object.fromEntries(fields.map((f) => [f.name, f])) as Partial<Record<FormFieldName<E>, FormField<FormFieldName<E>>>>,
63
+ values: values as FormValues<E>,
64
+ errors: errors as FormErrors<E>,
71
65
  submit,
72
66
  loading: command.loading,
73
67
  /** Non-validation failure of the last submit (unreachable host, conflict…). */
@@ -85,7 +85,8 @@ export function useCommand<
85
85
  const loading = ref(false);
86
86
  const error = ref<FougereError<Refused<Address, Op>> | null>(null);
87
87
 
88
- async function execute(input?: CallInput): Promise<Answered> {
88
+ /** The answer, or `null` when the call was refused — the refusal is in `error`, and nothing is thrown. */
89
+ async function execute(input?: CallInput): Promise<Answered | null> {
89
90
  loading.value = true;
90
91
  error.value = null;
91
92
  try {
@@ -97,7 +98,8 @@ export function useCommand<
97
98
  return result;
98
99
  } catch (err) {
99
100
  error.value = asFougereError(err, entityKey, op) as FougereError<Refused<Address, Op>>;
100
- throw error.value;
101
+
102
+ return null;
101
103
  } finally {
102
104
  loading.value = false;
103
105
  }