@voltro/client 0.50.1 → 0.52.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.
- package/CHANGELOG.md +231 -0
- package/dist/form.d.ts +127 -0
- package/dist/form.js +2 -0
- package/dist/formData-Bw07C0wr.js +155 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +1095 -1176
- package/package.json +8 -3
package/dist/index.d.ts
CHANGED
|
@@ -961,6 +961,22 @@ export declare type FilterKind = 'text' | 'select' | 'multi-select' | 'number-ra
|
|
|
961
961
|
* input field → one FilterDescriptor. Pure. */
|
|
962
962
|
export declare const filtersFromSchema: (schema: Schema.Schema.Any) => ReadonlyArray<FilterDescriptor>;
|
|
963
963
|
|
|
964
|
+
/** DOM id of the JSON script the 422 re-render embeds (survives the
|
|
965
|
+
* `interactive:'none'` strip — it is neither `type="module"` nor `src`). */
|
|
966
|
+
export declare const FORM_FLASH_SCRIPT_ID = "__voltro_form_flash__";
|
|
967
|
+
|
|
968
|
+
/** Hidden field carrying the form's instance key (multi-form pages). */
|
|
969
|
+
export declare const FORM_KEY_FIELD = "__voltro_form";
|
|
970
|
+
|
|
971
|
+
/** URL prefix the web listener mounts the no-JS endpoint under. */
|
|
972
|
+
export declare const FORM_PATH_PREFIX = "/form/";
|
|
973
|
+
|
|
974
|
+
/** Hidden field carrying the declared success-redirect path. */
|
|
975
|
+
export declare const FORM_REDIRECT_FIELD = "__voltro_redirect";
|
|
976
|
+
|
|
977
|
+
/** The path a native `<AutoForm>` POST goes to. */
|
|
978
|
+
export declare const formActionPath: (mutationTag: string) => string;
|
|
979
|
+
|
|
964
980
|
export declare interface FormBinding<Input, Output> {
|
|
965
981
|
/** Ordered, render-agnostic field list derived from the input schema. */
|
|
966
982
|
readonly fields: ReadonlyArray<FieldDescriptor>;
|
|
@@ -972,6 +988,9 @@ export declare interface FormBinding<Input, Output> {
|
|
|
972
988
|
readonly pending: boolean;
|
|
973
989
|
/** The mutation's typed failure, if the last submit threw. */
|
|
974
990
|
readonly submitError: unknown | undefined;
|
|
991
|
+
/** A form-level (non-field) error carried in from a failed no-JS POST —
|
|
992
|
+
* the RPC refused after valid input. Cleared by the next submit/reset. */
|
|
993
|
+
readonly formError: string | undefined;
|
|
975
994
|
readonly data: Output | undefined;
|
|
976
995
|
readonly setValue: (name: string, value: unknown) => void;
|
|
977
996
|
readonly setValues: (patch: Partial<Input>) => void;
|
|
@@ -981,6 +1000,50 @@ export declare interface FormBinding<Input, Output> {
|
|
|
981
1000
|
readonly submit: () => Promise<Output | undefined>;
|
|
982
1001
|
}
|
|
983
1002
|
|
|
1003
|
+
/**
|
|
1004
|
+
* Convert posted form entries into the input object the mutation's schema
|
|
1005
|
+
* decodes — the shape `validateFields` (and the RPC payload) expects.
|
|
1006
|
+
*
|
|
1007
|
+
* Mapping rules (the documented contract):
|
|
1008
|
+
* - **checkbox/switch**: present → `true`, absent → `false`. A native POST
|
|
1009
|
+
* omits an unchecked checkbox entirely, so absence is data, not a gap.
|
|
1010
|
+
* - **number**: `Number(raw)`; `''` → the field is omitted (`undefined`), so
|
|
1011
|
+
* an optional number stays absent and a required one reports "missing"
|
|
1012
|
+
* instead of silently becoming `0`.
|
|
1013
|
+
* - **date/datetime**: the string passes through (the schema's encoded side);
|
|
1014
|
+
* `''` → omitted, same reasoning as number.
|
|
1015
|
+
* - **arrays** (multi-select): `getAll` semantics — every entry under the key,
|
|
1016
|
+
* items converted per the array's item type (number items → `Number`).
|
|
1017
|
+
* - **unknown keys are dropped**: only names the schema declares are mapped,
|
|
1018
|
+
* so protocol fields (`__voltro_form`, …) never reach the input object —
|
|
1019
|
+
* the server rejects undeclared fields, and a hidden bookkeeping field must
|
|
1020
|
+
* not turn every no-JS submit into a validation error.
|
|
1021
|
+
*/
|
|
1022
|
+
export declare const formDataToInput: (schema: Schema.Schema.Any, entries: Iterable<FormEntry>) => Record<string, unknown>;
|
|
1023
|
+
|
|
1024
|
+
/** One posted entry. File entries must be filtered out by the caller —
|
|
1025
|
+
* uploads are a declared limit of the no-JS path. */
|
|
1026
|
+
export declare type FormEntry = readonly [name: string, value: string];
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* The error/values payload a failed no-JS form POST carries back into the
|
|
1030
|
+
* 422 re-render. Keyed by `formKey` so a page with several forms re-fills
|
|
1031
|
+
* only the one that was submitted. The SSR render passes it through the
|
|
1032
|
+
* server-request context; the client reads the same payload back off the
|
|
1033
|
+
* `#__voltro_form_flash__` JSON script, so a late-hydrating page shows the
|
|
1034
|
+
* identical state (no mismatch, no vanished errors).
|
|
1035
|
+
*/
|
|
1036
|
+
export declare interface FormFlashPayload {
|
|
1037
|
+
/** The submitted form's key — `<AutoForm formKey>` or its mutation tag. */
|
|
1038
|
+
readonly formKey: string;
|
|
1039
|
+
/** The mapped input values as posted (pre-decode), to re-fill the fields. */
|
|
1040
|
+
readonly values: Readonly<Record<string, unknown>>;
|
|
1041
|
+
/** First error per field — the `validateFields` shape. */
|
|
1042
|
+
readonly errors: Readonly<Record<string, string>>;
|
|
1043
|
+
/** A non-field error (the RPC refused after valid input: guard, server). */
|
|
1044
|
+
readonly formError?: string;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
984
1047
|
export declare interface FrameworkRuntimes {
|
|
985
1048
|
/** Look up an api handle (runtime + cache) by name. Throws if no such api was mounted. */
|
|
986
1049
|
readonly get: (name: string) => ApiHandle;
|
|
@@ -1010,6 +1073,32 @@ export declare const getMutationNotifier: () => MutationNotifier | undefined;
|
|
|
1010
1073
|
/** Read the current feed. Newest-first; up to MAX_MUTATIONS entries. */
|
|
1011
1074
|
export declare const getMutations: () => ReadonlyArray<MutationEvent>;
|
|
1012
1075
|
|
|
1076
|
+
/**
|
|
1077
|
+
* A process-wide singleton React context, pinned on the global symbol registry.
|
|
1078
|
+
*
|
|
1079
|
+
* WHY this exists: the SSG prerender (`voltro build`) loads the framework
|
|
1080
|
+
* through TWO separate module instances — the renderer comes in via Vite's
|
|
1081
|
+
* `ssrLoadModule('@voltro/web/ssr')` (Vite-transformed) while a page's own
|
|
1082
|
+
* framework import is externalised to Node — so a plain `createContext()`
|
|
1083
|
+
* in a shared module is evaluated twice and yields two DISTINCT context
|
|
1084
|
+
* objects. The `<Router>` provider then holds one while the page's
|
|
1085
|
+
* `useLocation()` reads the other, which throws "Router hooks must be used
|
|
1086
|
+
* inside <Router>." The same duplicate-instance hazard shows up wherever a
|
|
1087
|
+
* deployment ends up with two copies of a package (the classic dual-package
|
|
1088
|
+
* hazard, monorepo hoisting quirks, separate SSR vs client bundles).
|
|
1089
|
+
*
|
|
1090
|
+
* Resolving every context through `Symbol.for(...)` on `globalThis` makes all
|
|
1091
|
+
* module copies share ONE instance, so provider and consumer can never diverge.
|
|
1092
|
+
* A duplicated copy of THIS helper is harmless — both copies hit the same
|
|
1093
|
+
* global registry entry.
|
|
1094
|
+
*
|
|
1095
|
+
* Lives in @voltro/client (the lowest React-carrying package) so both
|
|
1096
|
+
* @voltro/web and @voltro/ui reach it without a cycle; the key prefix keeps
|
|
1097
|
+
* its historical spelling on purpose — a mixed dist/src world must resolve
|
|
1098
|
+
* to the same registry entries.
|
|
1099
|
+
*/
|
|
1100
|
+
export declare const globalContext: <T>(key: string, initial: T) => Context<T>;
|
|
1101
|
+
|
|
1013
1102
|
/** Is this the framework's `Unauthenticated`? Matched on `_tag`, the wire
|
|
1014
1103
|
* contract, rather than on an instance — the error crosses a package boundary
|
|
1015
1104
|
* and may be re-created by the decoder. */
|
|
@@ -1832,6 +1921,29 @@ export declare type SequenceResult<Ctx> = {
|
|
|
1832
1921
|
}>;
|
|
1833
1922
|
};
|
|
1834
1923
|
|
|
1924
|
+
export declare const ServerRequestContext: Context<ServerRequestContextValue | null>;
|
|
1925
|
+
|
|
1926
|
+
export declare interface ServerRequestContextValue {
|
|
1927
|
+
readonly cookies: Readonly<Record<string, string>>;
|
|
1928
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
1929
|
+
/** Raw request URL as it came off the wire (path + query). Useful
|
|
1930
|
+
* for SSR pages that need to read `?q=…` style search params
|
|
1931
|
+
* without touching anything client-only. Empty string for build-
|
|
1932
|
+
* time SSG renders where there is no incoming request. */
|
|
1933
|
+
readonly url: string;
|
|
1934
|
+
/** Present ONLY on the 422 re-render of a failed no-JS form POST:
|
|
1935
|
+
* the submitted values + field errors, keyed by formKey. Travels on
|
|
1936
|
+
* the EXISTING request context deliberately — a dedicated provider
|
|
1937
|
+
* would add a fiber fork the client boot does not have, and every
|
|
1938
|
+
* ancestor arity difference shifts every useId in the app. */
|
|
1939
|
+
readonly formFlash?: FormFlashPayload;
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
export declare const ServerRequestProvider: ({ value, children, }: {
|
|
1943
|
+
readonly value: ServerRequestContextValue;
|
|
1944
|
+
readonly children: ReactNode;
|
|
1945
|
+
}) => ReactNode;
|
|
1946
|
+
|
|
1835
1947
|
/** Register (or clear) the app-wide notifier that `notify:` routes to. Call once
|
|
1836
1948
|
* at boot, next to your toast provider. */
|
|
1837
1949
|
export declare const setMutationNotifier: (notifier: MutationNotifier | undefined) => void;
|
|
@@ -3048,8 +3160,27 @@ export declare interface UseFormBindingOptions<Input> {
|
|
|
3048
3160
|
readonly schema?: Schema.Schema.Any;
|
|
3049
3161
|
/** Initial field values. */
|
|
3050
3162
|
readonly defaults?: Partial<Input>;
|
|
3163
|
+
/** The failed no-JS POST's payload for THIS form (`useFormFlash` from
|
|
3164
|
+
* @voltro/web resolves it, SSR and client alike). When present it seeds
|
|
3165
|
+
* the initial values + field errors, so the 422 re-render shows the
|
|
3166
|
+
* submitted state server-side and hydrates to the identical state. */
|
|
3167
|
+
readonly flash?: FormFlashPayload | undefined;
|
|
3051
3168
|
}
|
|
3052
3169
|
|
|
3170
|
+
/**
|
|
3171
|
+
* The failed-no-JS-POST payload for ONE form, or `undefined`.
|
|
3172
|
+
*
|
|
3173
|
+
* On the server (the 422 re-render) it comes off the request context; on the
|
|
3174
|
+
* client it is read back from the `#__voltro_form_flash__` JSON script the
|
|
3175
|
+
* same response embedded. Both carry the SAME payload, so a page that loads
|
|
3176
|
+
* its bundle after a native submit hydrates to exactly the server-rendered
|
|
3177
|
+
* state — errors visible, values filled, no mismatch.
|
|
3178
|
+
*
|
|
3179
|
+
* Keyed: only the form whose `formKey` was submitted receives the payload —
|
|
3180
|
+
* two `<AutoForm>`s on one page re-fill only the one that POSTed.
|
|
3181
|
+
*/
|
|
3182
|
+
export declare const useFormFlash: (formKey: string) => FormFlashPayload | undefined;
|
|
3183
|
+
|
|
3053
3184
|
/** The field shape a `<AutoForm mutation=…>` will render — from the mutation's
|
|
3054
3185
|
* input Schema. Use it to render a matching skeleton while anything the form
|
|
3055
3186
|
* depends on is still loading. */
|
|
@@ -3198,6 +3329,8 @@ export declare interface UseSequenceResult {
|
|
|
3198
3329
|
readonly failedStep: string | undefined;
|
|
3199
3330
|
}
|
|
3200
3331
|
|
|
3332
|
+
export declare const useServerRequest: () => ServerRequestContextValue | null;
|
|
3333
|
+
|
|
3201
3334
|
export declare function useSubscription<T = unknown>(apiName: string, rpcTag: string, input: Readonly<Record<string, unknown>>, options: SubscriptionOptions<T> & {
|
|
3202
3335
|
readonly initialSnapshot: T;
|
|
3203
3336
|
}): SubscriptionStateWithFallback<T>;
|