gemi 0.4.13 → 0.4.14

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 (90) hide show
  1. package/dist/app/App.d.ts.map +1 -1
  2. package/dist/app/createFlatApiRoutes.d.ts.map +1 -1
  3. package/dist/app/index.js +220 -608
  4. package/dist/auth/AuthenticationServiceProvider.d.ts +54 -0
  5. package/dist/auth/AuthenticationServiceProvider.d.ts.map +1 -0
  6. package/dist/auth/adapters/blank.d.ts +10 -0
  7. package/dist/auth/adapters/blank.d.ts.map +1 -0
  8. package/dist/auth/adapters/types.d.ts +77 -0
  9. package/dist/auth/adapters/types.d.ts.map +1 -0
  10. package/dist/bin/index.js +13 -0
  11. package/dist/client/ClientRouter.d.ts.map +1 -1
  12. package/dist/client/ClientRouterContext.d.ts +2 -0
  13. package/dist/client/ClientRouterContext.d.ts.map +1 -1
  14. package/dist/client/Mutation.d.ts +25 -7
  15. package/dist/client/Mutation.d.ts.map +1 -1
  16. package/dist/client/QueryManager.d.ts +24 -0
  17. package/dist/client/QueryManager.d.ts.map +1 -0
  18. package/dist/client/QueryManagerContext.d.ts +8 -0
  19. package/dist/client/QueryManagerContext.d.ts.map +1 -0
  20. package/dist/client/ServerDataProvider.d.ts +1 -0
  21. package/dist/client/ServerDataProvider.d.ts.map +1 -1
  22. package/dist/client/{Form.d.ts → _Form.d.ts} +1 -1
  23. package/dist/client/_Form.d.ts.map +1 -0
  24. package/dist/client/auth/useForgotPassword.d.ts +17 -0
  25. package/dist/client/auth/useForgotPassword.d.ts.map +1 -0
  26. package/dist/client/auth/useResetPassword.d.ts +17 -0
  27. package/dist/client/auth/useResetPassword.d.ts.map +1 -0
  28. package/dist/client/auth/useSignIn.d.ts +24 -0
  29. package/dist/client/auth/useSignIn.d.ts.map +1 -0
  30. package/dist/client/auth/useSignOut.d.ts +17 -0
  31. package/dist/client/auth/useSignOut.d.ts.map +1 -0
  32. package/dist/client/auth/useSignUp.d.ts +21 -0
  33. package/dist/client/auth/useSignUp.d.ts.map +1 -0
  34. package/dist/client/auth/useUser.d.ts +2 -0
  35. package/dist/client/auth/useUser.d.ts.map +1 -0
  36. package/dist/client/index.d.ts +8 -4
  37. package/dist/client/index.d.ts.map +1 -1
  38. package/dist/client/index.js +392 -278
  39. package/dist/client/rpc.d.ts +3 -1
  40. package/dist/client/rpc.d.ts.map +1 -1
  41. package/dist/client/useMutation.d.ts +12 -3
  42. package/dist/client/useMutation.d.ts.map +1 -1
  43. package/dist/client/useQuery.d.ts +16 -6
  44. package/dist/client/useQuery.d.ts.map +1 -1
  45. package/dist/email/EmailServiceProvider.d.ts +1 -1
  46. package/dist/email/EmailServiceProvider.d.ts.map +1 -1
  47. package/dist/email/index.js +4745 -12
  48. package/dist/email/providers.d.ts +1 -1
  49. package/dist/email/providers.d.ts.map +1 -1
  50. package/dist/facades/Auth.d.ts +5 -0
  51. package/dist/facades/Auth.d.ts.map +1 -0
  52. package/dist/facades/Redirect.d.ts +4 -0
  53. package/dist/facades/Redirect.d.ts.map +1 -0
  54. package/dist/facades/index.d.ts +3 -0
  55. package/dist/facades/index.d.ts.map +1 -0
  56. package/dist/facades/index.js +81 -4
  57. package/dist/http/ApiRouter.d.ts +321 -15
  58. package/dist/http/ApiRouter.d.ts.map +1 -1
  59. package/dist/http/AuthenticationMiddlware.d.ts +6 -0
  60. package/dist/http/AuthenticationMiddlware.d.ts.map +1 -0
  61. package/dist/http/Controller.d.ts +10 -1
  62. package/dist/http/Controller.d.ts.map +1 -1
  63. package/dist/http/Cookie.d.ts +18 -0
  64. package/dist/http/Cookie.d.ts.map +1 -0
  65. package/dist/http/HttpRequest.d.ts +9 -1
  66. package/dist/http/HttpRequest.d.ts.map +1 -1
  67. package/dist/http/Middleware.d.ts +1 -1
  68. package/dist/http/Middleware.d.ts.map +1 -1
  69. package/dist/http/MiddlewareServiceProvider.d.ts +5 -0
  70. package/dist/http/MiddlewareServiceProvider.d.ts.map +1 -0
  71. package/dist/http/ViewRouter.d.ts +11 -11
  72. package/dist/http/ViewRouter.d.ts.map +1 -1
  73. package/dist/http/index.d.ts +3 -1
  74. package/dist/http/index.d.ts.map +1 -1
  75. package/dist/http/index.js +147 -13
  76. package/dist/http/requestContext.d.ts +17 -2
  77. package/dist/http/requestContext.d.ts.map +1 -1
  78. package/dist/kernel/KernelContext.d.ts +4 -0
  79. package/dist/kernel/KernelContext.d.ts.map +1 -0
  80. package/dist/kernel/context.d.ts +9 -0
  81. package/dist/kernel/context.d.ts.map +1 -0
  82. package/dist/server/index.js +13 -0
  83. package/dist/utils/autobind.d.ts +2 -0
  84. package/dist/utils/autobind.d.ts.map +1 -0
  85. package/dist/utils/debounce.d.ts +2 -0
  86. package/dist/utils/debounce.d.ts.map +1 -0
  87. package/dist/utils/type.d.ts +5 -0
  88. package/dist/utils/type.d.ts.map +1 -1
  89. package/package.json +3 -1
  90. package/dist/client/Form.d.ts.map +0 -1
@@ -10,303 +10,305 @@ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot
10
10
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
11
11
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
12
12
  var _i, _n, _t, _e, _s, _l, _o, _d, _p, _g, _H_instances, r_fn, R_fn, b_fn, u_fn, m_fn, a_fn, P_fn, E_fn, S_fn, O_fn, k_fn, x_fn, h_fn, f_fn, T_fn, A_fn, y_fn, w_fn, c_fn, C_fn, _a, _i2, _n2, _t2, _e2, _s2, _l2, _b;
13
- import require$$1, { createContext, useContext, useState, useEffect, useRef, lazy, startTransition, StrictMode, Suspense } from "react";
13
+ import require$$1, { createContext, useState, useEffect, useContext, useSyncExternalStore, useRef, lazy, startTransition, StrictMode, Suspense } from "react";
14
14
  import { jsx, Fragment } from "react/jsx-runtime";
15
15
  import require$$2 from "react-dom";
16
- const ServerDataContext = createContext({});
17
- const ServerDataProvider = (props) => {
18
- let _value = props.value;
19
- if (props.value) {
20
- _value = props.value;
21
- } else {
22
- _value = window.__GEMI_DATA__;
16
+ class Subject {
17
+ constructor(initialValue) {
18
+ __publicField(this, "subscribers", /* @__PURE__ */ new Set());
19
+ __publicField(this, "value");
20
+ this.value = initialValue;
23
21
  }
24
- return /* @__PURE__ */ jsx(ServerDataContext.Provider, { value: _value, children: props.children });
25
- };
26
- function useUser() {
27
- const { auth } = useContext(ServerDataContext);
28
- const [user, setUser] = useState((auth == null ? void 0 : auth.user) ?? {});
29
- useEffect(() => {
30
- if (auth == null ? void 0 : auth.user) {
31
- setUser(auth == null ? void 0 : auth.user);
22
+ subscribe(subscriber) {
23
+ this.subscribers.add(subscriber);
24
+ return () => {
25
+ this.subscribers.delete(subscriber);
26
+ };
27
+ }
28
+ next(value) {
29
+ this.value = value;
30
+ this.subscribers.forEach((subscriber) => subscriber(value));
31
+ }
32
+ getValue() {
33
+ return this.value;
34
+ }
35
+ }
36
+ function applyParams$1(url, params = {}) {
37
+ let out = url;
38
+ for (const segment of url.split("/")) {
39
+ if (segment.includes(":")) {
40
+ const key = segment.split(":")[1];
41
+ out = out.replace(`:${key}`, params[key]);
32
42
  }
33
- }, [auth == null ? void 0 : auth.user]);
34
- return user;
43
+ }
44
+ return out;
35
45
  }
36
- function useQuery(url, options) {
37
- const [data, setData] = useState(null);
38
- const [loading, setLoading] = useState(true);
39
- const [error, setError] = useState(null);
40
- useEffect(() => {
41
- async function execute() {
42
- setLoading(true);
43
- try {
44
- const [, _url] = String(url).split(":");
45
- const res = await fetch(`/api${url}`);
46
- if (res.ok) {
47
- const json = await res.json();
48
- setData(json);
49
- }
50
- } catch (err) {
51
- setError(JSON.stringify(err));
52
- } finally {
53
- setLoading(false);
46
+ class Resource {
47
+ constructor(key, fallbackData = null) {
48
+ __publicField(this, "key");
49
+ __publicField(this, "state");
50
+ __publicField(this, "stale", true);
51
+ __publicField(this, "staleTimer", null);
52
+ this.key = key;
53
+ this.state = new Subject({
54
+ data: fallbackData,
55
+ error: null,
56
+ loading: false
57
+ });
58
+ if (fallbackData) {
59
+ this.stale = false;
60
+ }
61
+ }
62
+ mutate(fn) {
63
+ const data = fn(this.state.getValue().data);
64
+ this.state.next({
65
+ data,
66
+ error: null,
67
+ loading: false
68
+ });
69
+ }
70
+ fetch() {
71
+ const { loading, data, error } = this.state.getValue();
72
+ if (loading) {
73
+ return this.state;
74
+ }
75
+ if (!data) {
76
+ this.state.next({
77
+ data,
78
+ error,
79
+ loading: true
80
+ });
81
+ this.resolve();
82
+ } else {
83
+ if (this.stale) {
84
+ this.resolve();
85
+ return this.state;
54
86
  }
55
87
  }
56
- execute();
57
- }, [url, options]);
58
- return { data, loading, error };
88
+ return this.state;
89
+ }
90
+ resolve() {
91
+ const { key, options } = JSON.parse(this.key);
92
+ const { query, params } = options;
93
+ const url = key.split("GET:")[1];
94
+ const searchParams = new URLSearchParams(query);
95
+ const finalUrl = [applyParams$1(url, params), searchParams.toString()].filter((s) => s.length > 0).join("?");
96
+ fetch(`/api${finalUrl}`, {
97
+ method: "GET",
98
+ headers: {
99
+ "Content-Type": "application/json"
100
+ }
101
+ }).then((res) => {
102
+ if (res.ok) {
103
+ return res.json();
104
+ } else {
105
+ throw new Error("Failed to fetch");
106
+ }
107
+ }).then((data) => {
108
+ this.stale = false;
109
+ this.mutate(() => data);
110
+ clearTimeout(this.staleTimer);
111
+ this.staleTimer = setTimeout(() => {
112
+ this.stale = true;
113
+ }, 1e3 * 60);
114
+ }).catch((err) => {
115
+ this.state.next({
116
+ data: null,
117
+ error: err,
118
+ loading: false
119
+ });
120
+ });
121
+ }
122
+ }
123
+ class QueryManager {
124
+ constructor() {
125
+ __publicField(this, "resources", /* @__PURE__ */ new Map());
126
+ }
127
+ createResourceKey(key, options = {}) {
128
+ return JSON.stringify({ key, options });
129
+ }
130
+ fetch(key, options = {}, config = {}) {
131
+ const resourceKey = this.createResourceKey(key, options);
132
+ if (!this.resources.has(resourceKey)) {
133
+ this.resources.set(
134
+ resourceKey,
135
+ new Resource(resourceKey, config.fallbackData)
136
+ );
137
+ }
138
+ const resource = this.resources.get(resourceKey);
139
+ resource.fetch.call(resource);
140
+ return resource;
141
+ }
142
+ }
143
+ const QueryManagerContext = createContext(
144
+ {}
145
+ );
146
+ const QueryManagerProvider = ({ children }) => {
147
+ const [manager] = useState(() => new QueryManager());
148
+ useEffect(() => {
149
+ if (typeof window !== void 0) {
150
+ window.qm = manager;
151
+ }
152
+ }, [manager]);
153
+ return /* @__PURE__ */ jsx(QueryManagerContext.Provider, { value: { manager }, children });
154
+ };
155
+ const defaultConfig = {
156
+ pathPrefix: "",
157
+ fallbackData: null
158
+ };
159
+ function useQuery(url, ...args) {
160
+ const defaultOptions2 = {
161
+ params: {},
162
+ query: {}
163
+ };
164
+ const [options = defaultOptions2, config = defaultConfig] = args;
165
+ const { manager } = useContext(QueryManagerContext);
166
+ const [, path] = url.split("GET:");
167
+ const fullUrl = ["GET:", config.pathPrefix, path].join("");
168
+ const [resource] = useState(
169
+ () => manager.fetch(fullUrl, options, { fallbackData: config.fallbackData })
170
+ );
171
+ const state = useSyncExternalStore(
172
+ resource.state.subscribe.bind(resource.state),
173
+ resource.state.getValue.bind(resource.state),
174
+ resource.state.getValue.bind(resource.state)
175
+ );
176
+ return {
177
+ data: state.data,
178
+ loading: state.loading,
179
+ error: state.error,
180
+ mutate: resource.mutate.bind(resource)
181
+ };
59
182
  }
60
183
  function applyParams(url, params = {}) {
61
184
  let out = url;
62
185
  for (const [key, value] of Object.entries(params)) {
63
- out.replace(`:${key}?`, value);
64
- out.replace(`:${key}`, value);
186
+ out = out.replace(`:${key}?`, value).replace(`:${key}`, value);
65
187
  }
66
188
  return out;
67
189
  }
190
+ const defaultOptions = {
191
+ autoInvalidate: false,
192
+ pathPrefix: "",
193
+ onSuccess: () => {
194
+ },
195
+ onError: () => {
196
+ }
197
+ };
68
198
  function useMutation(url, ...args) {
69
- const [loading, setIsPending] = useState(false);
70
- const [data, setData] = useState(null);
199
+ const [state, setState] = useState({
200
+ data: null,
201
+ error: null,
202
+ loading: false
203
+ });
71
204
  return {
72
- data,
73
- loading,
74
- error: {},
205
+ ...state,
75
206
  trigger: async (input) => {
76
- setIsPending(true);
77
- const [inputs, _options] = args;
207
+ setState((state2) => ({
208
+ data: state2.data,
209
+ error: state2.error,
210
+ loading: true
211
+ }));
212
+ const [inputs = { params: {}, query: {} }, options = defaultOptions] = args ?? [];
213
+ const { pathPrefix } = options;
214
+ const { query = {} } = inputs ?? {};
78
215
  const params = "params" in inputs ? inputs.params : {};
79
- const [method, _url] = String(url).split(":");
80
- const finalUrl = applyParams(_url, params);
81
- const response = await fetch(`/api${finalUrl}`, {
216
+ const [method] = String(url).split(":");
217
+ const finalUrl = [
218
+ applyParams(String(url).replace(`${method}:`, ""), params),
219
+ new URLSearchParams(query).toString()
220
+ ].join("?");
221
+ let body = null;
222
+ const contentType = input instanceof FormData ? {} : { "Content-Type": "application/json" };
223
+ if (input instanceof FormData) {
224
+ body = input;
225
+ } else if (input) {
226
+ body = JSON.stringify(input);
227
+ }
228
+ const response = await fetch(`/api${pathPrefix}${finalUrl}`, {
82
229
  method,
83
230
  headers: {
84
- "Content-Type": "application/json"
231
+ ...contentType
85
232
  },
86
- ...input ? { body: JSON.stringify(input) } : {}
87
- });
88
- const data2 = await response.json();
89
- setData(data2);
90
- setIsPending(false);
91
- return data2;
92
- }
93
- };
94
- }
95
- class InputSubject {
96
- constructor(initialValue, type, autoFocus = false, validateFn) {
97
- __publicField(this, "type");
98
- __publicField(this, "state", {
99
- isDirty: false,
100
- value: null,
101
- error: null,
102
- isFocused: false,
103
- isTouched: false,
104
- isInvalid: false
105
- });
106
- __publicField(this, "subscribers", /* @__PURE__ */ new Set());
107
- __publicField(this, "validateFn");
108
- __publicField(this, "subscribe", (fn) => {
109
- this.subscribers.add(fn);
110
- return () => {
111
- this.subscribers.delete(fn);
112
- };
113
- });
114
- __publicField(this, "getState", () => {
115
- return this.state;
116
- });
117
- __publicField(this, "next", (state) => {
118
- this.state = {
119
- ...this.state,
120
- ...state,
121
- isInvalid: !!state.error
122
- };
123
- this.subscribers.forEach((subscriber) => {
124
- subscriber(this.state);
233
+ ...body ? { body } : {}
125
234
  });
126
- });
127
- this.state.isFocused = autoFocus;
128
- this.state.value = initialValue;
129
- this.validateFn = validateFn ?? (() => null);
130
- this.type = type;
131
- }
132
- }
133
- const FormContext = createContext({});
134
- const inputTypeInitialValueMap = {
135
- text: "",
136
- number: 0,
137
- checkbox: false,
138
- email: "",
139
- password: ""
140
- };
141
- function Form(props) {
142
- const { onSubmit, schema, ...rest } = props;
143
- const inputSubjectsRef = useRef(/* @__PURE__ */ new Map());
144
- const getInputValueSubject = (props2) => {
145
- if (!inputSubjectsRef.current.has(props2.name)) {
146
- const initialValue = props2.value ?? props2.defaultValue ?? (inputTypeInitialValueMap == null ? void 0 : inputTypeInitialValueMap[props2.type]) ?? "";
147
- inputSubjectsRef.current.set(
148
- props2.name,
149
- new InputSubject(
150
- initialValue,
151
- props2.type ?? "text",
152
- props2.autoFocus,
153
- props2.validate
154
- )
155
- );
156
- }
157
- return inputSubjectsRef.current.get(props2.name);
158
- };
159
- const getInputValueSubjectByName = (name) => {
160
- return inputSubjectsRef.current.get(name);
161
- };
162
- const validateSingleField = (name, value) => {
163
- let values = {};
164
- for (const [name2, inputSubject2] of inputSubjectsRef.current.entries()) {
165
- const { value: value2 } = inputSubject2.getState();
166
- values[name2] = value2;
167
- }
168
- values[name] = value;
169
- const inputSubject = inputSubjectsRef.current.get(name);
170
- if (inputSubject) {
171
- const error = inputSubject.validateFn(value);
172
- if (error) {
173
- return error;
174
- }
175
- if (schema) {
176
- const result = schema.safeParse(values);
177
- if (!result.success) {
178
- for (let schemaError of result.error.errors) {
179
- if (schemaError.path[0] === name) {
180
- return schemaError.message;
181
- }
182
- }
235
+ try {
236
+ const data = await response.json();
237
+ if (!response.ok) {
238
+ setState(() => ({
239
+ data: null,
240
+ error: data.error,
241
+ loading: false
242
+ }));
243
+ return;
183
244
  }
184
- }
185
- }
186
- return null;
187
- };
188
- const beforeSubmit = () => {
189
- let values = {};
190
- let errors = {};
191
- for (const [name, inputSubject] of inputSubjectsRef.current.entries()) {
192
- const { value } = inputSubject.getState();
193
- const error = inputSubject.validateFn(values[name]);
194
- values[name] = value;
195
- errors[name] = error;
196
- }
197
- if (schema) {
198
- const result = schema.safeParse(values);
199
- if (!result.success) {
200
- result.error.errors.reverse().forEach((schemaError) => {
201
- errors[String(schemaError.path[0])] = schemaError.message;
245
+ options.onSuccess(data);
246
+ setState({
247
+ data,
248
+ error: null,
249
+ loading: false
202
250
  });
251
+ return data;
252
+ } catch (error) {
253
+ setState((state2) => ({
254
+ data: state2.data,
255
+ error,
256
+ loading: false
257
+ }));
203
258
  }
204
259
  }
205
- for (const [name, inputSubject] of inputSubjectsRef.current.entries()) {
206
- const error = errors[name] ? errors[name] : null;
207
- inputSubject == null ? void 0 : inputSubject.next({ error, isTouched: true });
208
- }
209
- return {
210
- errors,
211
- values
212
- };
213
260
  };
214
- const reset = () => {
215
- for (const [, inputSubject] of inputSubjectsRef.current.entries()) {
216
- inputSubject.next({
217
- error: null,
218
- isDirty: false,
219
- isTouched: false,
220
- isInvalid: false,
221
- value: (inputTypeInitialValueMap == null ? void 0 : inputTypeInitialValueMap[inputSubject.type]) ?? ""
222
- });
223
- }
224
- };
225
- return /* @__PURE__ */ jsx(
226
- FormContext.Provider,
227
- {
228
- value: {
229
- getInputValueSubject,
230
- getInputValueSubjectByName,
231
- validateSingleField
232
- },
233
- children: /* @__PURE__ */ jsx(
234
- "form",
235
- {
236
- ...rest,
237
- onSubmit: (e) => {
238
- e.preventDefault();
239
- const { errors, values } = beforeSubmit();
240
- const hasErrors = Object.values(errors).some((error) => error);
241
- if (!hasErrors) {
242
- onSubmit(e, { values, reset });
243
- }
244
- }
245
- }
246
- )
247
- }
248
- );
249
261
  }
250
262
  const MutationContext = createContext({
251
263
  isPending: false,
252
264
  result: null
253
265
  });
254
- const Mutation = (props) => {
255
- const { method = "POST" } = props;
256
- const [isPending, setIsPending] = useState(false);
266
+ function Form(props) {
267
+ const {
268
+ action,
269
+ pathPrefix,
270
+ onSuccess,
271
+ onError,
272
+ params,
273
+ className,
274
+ ...formProps
275
+ } = "params" in props ? props : { ...props, params: {} };
257
276
  const formRef = useRef(null);
258
- const [result, setResult] = useState(null);
259
- const [formError, setFormError] = useState(null);
260
- const [validationErrors, setValidationErrors] = useState({});
261
- const action = async (e) => {
262
- e.preventDefault();
263
- const formData = new FormData(formRef.current);
264
- setIsPending(true);
265
- setResult(null);
266
- try {
267
- const res = await fetch(`/api${props.url}`, {
268
- method,
269
- body: formData
270
- });
271
- const data = await res.json();
272
- if (!res.ok) {
273
- if ("error" in data) {
274
- if (data.error.kind === "validation_error") {
275
- setValidationErrors(data.error.messages);
276
- }
277
- if (data.error.kind === "form_error") {
278
- console.log(data.error.message);
279
- setFormError(data.error.message);
280
- }
281
- }
282
- } else {
283
- if (props.onSuccess) {
284
- props.onSuccess(data);
285
- }
286
- setResult(data);
287
- }
288
- } catch (err) {
289
- console.log(err);
277
+ const { trigger, data, error, loading } = useMutation(
278
+ action,
279
+ {
280
+ params
281
+ },
282
+ {
283
+ pathPrefix,
284
+ onSuccess,
285
+ onError
290
286
  }
291
- setIsPending(false);
287
+ );
288
+ const handleSubmit = async (e) => {
289
+ e.preventDefault();
290
+ trigger(new FormData(formRef.current));
292
291
  };
292
+ const validationErrors = (error == null ? void 0 : error.kind) === "validation_error" ? error.messages : {};
293
+ const formError = (error == null ? void 0 : error.kind) === "form_error" ? error.message : null;
293
294
  return /* @__PURE__ */ jsx(
294
295
  MutationContext.Provider,
295
296
  {
296
- value: { isPending, result, validationErrors, formError },
297
+ value: { isPending: loading, result: data, validationErrors, formError },
297
298
  children: /* @__PURE__ */ jsx(
298
299
  "form",
299
300
  {
300
- className: "group",
301
- "data-pending": isPending,
301
+ className: ["group", className].filter(Boolean).join(" "),
302
+ "data-loading": loading,
302
303
  ref: formRef,
303
- onSubmit: action,
304
+ onSubmit: handleSubmit,
305
+ ...formProps,
304
306
  children: props.children
305
307
  }
306
308
  )
307
309
  }
308
310
  );
309
- };
311
+ }
310
312
  function useMutationStatus() {
311
313
  const { isPending } = useContext(MutationContext);
312
314
  return { isPending };
@@ -326,6 +328,12 @@ const ValidationErrors = (props) => {
326
328
  }
327
329
  return null;
328
330
  };
331
+ const FormField = (props) => {
332
+ const { name, children, ...rest } = props;
333
+ const { validationErrors } = useContext(MutationContext);
334
+ const errors = validationErrors[name] || [];
335
+ return /* @__PURE__ */ jsx("div", { "data-hasError": errors.length > 0, ...rest, children });
336
+ };
329
337
  const FormError = (props) => {
330
338
  const { formError } = useContext(MutationContext);
331
339
  if (formError) {
@@ -586,26 +594,6 @@ function parsePath(path) {
586
594
  }
587
595
  return parsedPath;
588
596
  }
589
- class Subject {
590
- constructor(initialValue) {
591
- __publicField(this, "subscribers", /* @__PURE__ */ new Set());
592
- __publicField(this, "value");
593
- this.value = initialValue;
594
- }
595
- subscribe(subscriber) {
596
- this.subscribers.add(subscriber);
597
- return () => {
598
- this.subscribers.delete(subscriber);
599
- };
600
- }
601
- next(value) {
602
- this.value = value;
603
- this.subscribers.forEach((subscriber) => subscriber(value));
604
- }
605
- getValue() {
606
- return this.value;
607
- }
608
- }
609
597
  function flattenComponentTree(componentTree) {
610
598
  let out = [];
611
599
  for (const [root, branches] of componentTree) {
@@ -1344,7 +1332,8 @@ const ClientRouterProvider = (props) => {
1344
1332
  is404,
1345
1333
  routeManifest,
1346
1334
  pageData,
1347
- params
1335
+ params,
1336
+ searchParams
1348
1337
  } = props;
1349
1338
  const [parameters, setParameters] = useState(params);
1350
1339
  const pageDataRef = useRef(structuredClone(pageData));
@@ -1355,7 +1344,7 @@ const ClientRouterProvider = (props) => {
1355
1344
  () => new Subject({
1356
1345
  hash: "",
1357
1346
  pathname: currentPath,
1358
- search: "",
1347
+ search: searchParams,
1359
1348
  state: {},
1360
1349
  key: ""
1361
1350
  })
@@ -1450,12 +1439,30 @@ function useParams() {
1450
1439
  const { params } = useContext(ClientRouterContext);
1451
1440
  return params;
1452
1441
  }
1442
+ function useSearchParams() {
1443
+ const { locationSubject, history } = useContext(ClientRouterContext);
1444
+ const location = useLocation();
1445
+ const searchParams = new URLSearchParams(location.search);
1446
+ const setSearchParams = (newSearchParams) => {
1447
+ let nextSearchParams = newSearchParams;
1448
+ if (typeof newSearchParams === "function") {
1449
+ nextSearchParams = newSearchParams(searchParams);
1450
+ }
1451
+ locationSubject.next({
1452
+ ...locationSubject.getValue(),
1453
+ search: nextSearchParams.toString()
1454
+ });
1455
+ history == null ? void 0 : history.push({
1456
+ search: nextSearchParams.toString()
1457
+ });
1458
+ };
1459
+ return [searchParams, setSearchParams];
1460
+ }
1453
1461
  function useRouter() {
1454
1462
  const { updatePageData, history, getViewPathsFromPathname } = useContext(ClientRouterContext);
1455
1463
  useContext(ComponentsContext);
1456
1464
  return {
1457
1465
  push: async (to, state) => {
1458
- var _a2;
1459
1466
  let path = "";
1460
1467
  let urlSearchParams;
1461
1468
  let hash = "";
@@ -1478,8 +1485,7 @@ function useRouter() {
1478
1485
  ...components.map((component) => window.loaders[component]())
1479
1486
  ]);
1480
1487
  if (res.ok) {
1481
- const { data } = await res.json();
1482
- const is404 = ((_a2 = Object.values(data[to])[0]) == null ? void 0 : _a2.status) === 404;
1488
+ const { data, is404 = false } = await res.json();
1483
1489
  updatePageData(data);
1484
1490
  history == null ? void 0 : history.push(to, is404 ? { status: 404 } : state);
1485
1491
  window.scrollTo(0, 0);
@@ -30151,6 +30157,16 @@ if (process.env.NODE_ENV === "production") {
30151
30157
  client.exports = requireReactDomClient_development();
30152
30158
  }
30153
30159
  var clientExports = client.exports;
30160
+ const ServerDataContext = createContext({});
30161
+ const ServerDataProvider = (props) => {
30162
+ let _value = props.value;
30163
+ if (props.value) {
30164
+ _value = props.value;
30165
+ } else {
30166
+ _value = window.__GEMI_DATA__;
30167
+ }
30168
+ return /* @__PURE__ */ jsx(ServerDataContext.Provider, { value: _value, children: props.children });
30169
+ };
30154
30170
  const Route = (props) => {
30155
30171
  const { componentPath } = props;
30156
30172
  const { viewImportMap: viewImportMap2 } = useContext(ComponentsContext);
@@ -30190,9 +30206,10 @@ const Routes = (props) => {
30190
30206
  const ClientRouter = (props) => {
30191
30207
  const { RootLayout } = props;
30192
30208
  const { routeManifest, router, componentTree, pageData, auth } = useContext(ServerDataContext);
30193
- return /* @__PURE__ */ jsx(ComponentsProvider, { viewImportMap: props.viewImportMap, children: /* @__PURE__ */ jsx(
30209
+ return /* @__PURE__ */ jsx(QueryManagerProvider, { children: /* @__PURE__ */ jsx(ComponentsProvider, { viewImportMap: props.viewImportMap, children: /* @__PURE__ */ jsx(
30194
30210
  ClientRouterProvider,
30195
30211
  {
30212
+ searchParams: router.searchParams,
30196
30213
  params: router.params,
30197
30214
  pageData,
30198
30215
  is404: router.is404,
@@ -30201,7 +30218,7 @@ const ClientRouter = (props) => {
30201
30218
  routeManifest,
30202
30219
  children: /* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(RootLayout, { children: /* @__PURE__ */ jsx(Routes, { componentTree }) }) })
30203
30220
  }
30204
- ) });
30221
+ ) }) });
30205
30222
  };
30206
30223
  function init(RootLayout) {
30207
30224
  clientExports.hydrateRoot(
@@ -30268,20 +30285,117 @@ const Image = (props) => {
30268
30285
  );
30269
30286
  return /* @__PURE__ */ jsx("img", { ...srcProps, width, ...rest });
30270
30287
  };
30288
+ const defaultArgs$3 = {
30289
+ onSuccess: () => {
30290
+ }
30291
+ };
30292
+ function useForgotPassword(args = defaultArgs$3) {
30293
+ return useMutation(
30294
+ "POST:/forgot-password",
30295
+ {},
30296
+ {
30297
+ pathPrefix: "/auth",
30298
+ onSuccess: () => {
30299
+ args.onSuccess();
30300
+ }
30301
+ }
30302
+ );
30303
+ }
30304
+ const defaultArgs$2 = {
30305
+ onSuccess: () => {
30306
+ }
30307
+ };
30308
+ function useSignIn(args = defaultArgs$2) {
30309
+ const { mutate } = useQuery(
30310
+ "GET:/me",
30311
+ { params: {}, query: {} },
30312
+ { pathPrefix: "/auth" }
30313
+ );
30314
+ return useMutation(
30315
+ "POST:/sign-in",
30316
+ {},
30317
+ {
30318
+ pathPrefix: "/auth",
30319
+ onSuccess: ({ user }) => {
30320
+ args.onSuccess(user);
30321
+ mutate(user);
30322
+ }
30323
+ }
30324
+ );
30325
+ }
30326
+ function useSignUp() {
30327
+ return useMutation("POST:/sign-up", {}, { pathPrefix: "/auth" });
30328
+ }
30329
+ const defaultArgs$1 = {
30330
+ onSuccess: () => {
30331
+ }
30332
+ };
30333
+ function useSignOut(args = defaultArgs$1) {
30334
+ const { mutate } = useQuery(
30335
+ "GET:/me",
30336
+ { params: {}, query: {} },
30337
+ { pathPrefix: "/auth" }
30338
+ );
30339
+ return useMutation(
30340
+ "POST:/sign-out",
30341
+ {},
30342
+ {
30343
+ pathPrefix: "/auth",
30344
+ onSuccess: () => {
30345
+ args.onSuccess();
30346
+ mutate(null);
30347
+ }
30348
+ }
30349
+ );
30350
+ }
30351
+ const defaultArgs = {
30352
+ onSuccess: () => {
30353
+ }
30354
+ };
30355
+ function useResetPassword(args = defaultArgs) {
30356
+ return useMutation(
30357
+ "POST:/reset-password",
30358
+ {},
30359
+ {
30360
+ pathPrefix: "/auth",
30361
+ onSuccess: () => {
30362
+ args.onSuccess();
30363
+ }
30364
+ }
30365
+ );
30366
+ }
30367
+ function useUser() {
30368
+ const { auth } = useContext(ServerDataContext);
30369
+ const { data, loading } = useQuery(
30370
+ "GET:/me",
30371
+ { params: {}, query: {} },
30372
+ { fallbackData: { user: auth.user }, pathPrefix: "/auth" }
30373
+ );
30374
+ if (loading) {
30375
+ return null;
30376
+ }
30377
+ return data.user;
30378
+ }
30271
30379
  export {
30272
30380
  Form,
30273
30381
  FormError,
30382
+ FormField,
30274
30383
  Image,
30275
30384
  Link,
30276
- Mutation,
30277
30385
  ValidationErrors,
30278
30386
  createRoot,
30279
30387
  init,
30388
+ useForgotPassword,
30280
30389
  useLocation,
30281
30390
  useMutation,
30282
30391
  useMutationStatus,
30283
30392
  useParams,
30284
30393
  useQuery,
30394
+ useResetPassword,
30285
30395
  useRouter,
30396
+ useSearchParams,
30397
+ useSignIn,
30398
+ useSignOut,
30399
+ useSignUp,
30286
30400
  useUser
30287
30401
  };