arcway 0.1.25 → 0.1.27

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 (55) hide show
  1. package/client/fetcher.js +4 -1
  2. package/client/hooks/swr-compat.js +27 -0
  3. package/client/hooks/use-api-paginated.js +74 -0
  4. package/client/hooks/use-api.js +1 -4
  5. package/client/hooks/use-graphql.js +1 -2
  6. package/client/hooks/use-mutation.js +1 -1
  7. package/client/hooks/web/use-local-storage.js +54 -16
  8. package/client/index.js +16 -55
  9. package/client/router.js +51 -29
  10. package/client/ui/index.js +62 -380
  11. package/package.json +4 -3
  12. package/server/bin/commands/build.js +3 -0
  13. package/server/boot/index.js +12 -6
  14. package/server/build.js +63 -5
  15. package/server/cache/index.js +12 -2
  16. package/server/cache/ttl.js +24 -0
  17. package/server/config/duration.js +49 -0
  18. package/server/config/modules/cache.js +7 -1
  19. package/server/config/modules/jobs.js +14 -1
  20. package/server/config/modules/mail.js +16 -1
  21. package/server/config/modules/pages.js +3 -2
  22. package/server/config/modules/queue.js +7 -1
  23. package/server/config/modules/server.js +13 -1
  24. package/server/config/modules/websocket.js +8 -0
  25. package/server/context.js +61 -2
  26. package/server/db/index.js +6 -1
  27. package/server/events/drivers/memory.js +22 -4
  28. package/server/events/drivers/redis.js +20 -5
  29. package/server/events/handler.js +21 -7
  30. package/server/events/index.js +2 -2
  31. package/server/index.js +7 -33
  32. package/server/jobs/runner.js +3 -2
  33. package/server/jobs/worker-config.js +58 -0
  34. package/server/jobs/worker-entry.js +7 -12
  35. package/server/meta.js +106 -0
  36. package/server/pages/build-client.js +1 -1
  37. package/server/pages/build-plugins.js +2 -1
  38. package/server/pages/chunk-graph.js +1 -0
  39. package/server/pages/fonts.js +14 -1
  40. package/server/pages/handler.js +25 -7
  41. package/server/pages/lazy-context.js +2 -2
  42. package/server/pages/out-dir.js +104 -3
  43. package/server/pages/pages-router.js +3 -2
  44. package/server/pages/ssr.js +55 -18
  45. package/server/pages/vite-dev.js +38 -3
  46. package/server/router/api-router.js +71 -2
  47. package/server/router/ratelimit.js +50 -0
  48. package/server/router/routes.js +10 -0
  49. package/server/server.js +13 -1
  50. package/server/session/index.js +5 -1
  51. package/server/static/index.js +5 -2
  52. package/server/web-server.js +3 -3
  53. package/server/ws/realtime.js +24 -8
  54. package/server/ws/ws-router.js +24 -8
  55. package/client/hooks/use-form.js +0 -86
@@ -5,6 +5,19 @@ import { parseCookies, resolveSession, flattenHeaders } from '../session/helpers
5
5
  import { getMiddlewareForRoute } from '../router/middleware.js';
6
6
  import { toErrorMessage } from '../helpers.js';
7
7
 
8
+ function normalizeWsMsg(wsMsg) {
9
+ const rawPath = wsMsg.path;
10
+ const url = new URL(rawPath, 'http://localhost');
11
+ const query = Object.fromEntries(url.searchParams.entries());
12
+
13
+ return {
14
+ ...wsMsg,
15
+ path: rawPath,
16
+ pathname: url.pathname,
17
+ query: { ...query, ...(wsMsg.query ?? {}) },
18
+ };
19
+ }
20
+
8
21
  class WsRouter {
9
22
  _apiRouter;
10
23
  _log;
@@ -149,16 +162,17 @@ class WsRouter {
149
162
  return;
150
163
  }
151
164
 
152
- const method = parsed.method.toUpperCase();
165
+ const normalized = normalizeWsMsg(parsed);
166
+ const method = normalized.method.toUpperCase();
153
167
  if (method === 'SUBSCRIBE') {
154
- await this._handleSubscribe(client, { ...parsed, method });
168
+ await this._handleSubscribe(client, { ...normalized, method });
155
169
  } else if (method === 'UNSUBSCRIBE') {
156
- await this._handleUnsubscribe(client, { ...parsed, method });
170
+ await this._handleUnsubscribe(client, { ...normalized, method });
157
171
  } else if (['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
158
- await this._handleMethodCall(client, { ...parsed, method });
172
+ await this._handleMethodCall(client, { ...normalized, method });
159
173
  } else {
160
174
  this._send(client, {
161
- path: parsed.path,
175
+ path: normalized.path,
162
176
  error: { code: 'INVALID_METHOD', message: `Unsupported method: ${method}` },
163
177
  });
164
178
  }
@@ -167,6 +181,7 @@ class WsRouter {
167
181
  // ── Subscribe / Unsubscribe ──
168
182
 
169
183
  async _handleSubscribe(client, wsMsg) {
184
+ wsMsg = wsMsg.pathname ? wsMsg : normalizeWsMsg(wsMsg);
170
185
  const msgPath = wsMsg.path;
171
186
  if (client.subscriptions.has(msgPath)) {
172
187
  this._send(client, {
@@ -176,7 +191,7 @@ class WsRouter {
176
191
  return;
177
192
  }
178
193
 
179
- const matched = this._apiRouter.findRoute('GET', msgPath);
194
+ const matched = this._apiRouter.findRoute('GET', wsMsg.pathname);
180
195
  if (!matched) {
181
196
  this._send(client, {
182
197
  path: msgPath,
@@ -296,8 +311,9 @@ class WsRouter {
296
311
  // ── Method calls (GET/POST/PUT/PATCH/DELETE) ──
297
312
 
298
313
  async _handleMethodCall(client, wsMsg) {
314
+ wsMsg = wsMsg.pathname ? wsMsg : normalizeWsMsg(wsMsg);
299
315
  const { path: msgPath, method } = wsMsg;
300
- const matched = this._apiRouter.findRoute(method, msgPath);
316
+ const matched = this._apiRouter.findRoute(method, wsMsg.pathname);
301
317
 
302
318
  if (!matched) {
303
319
  this._send(client, {
@@ -330,7 +346,7 @@ class WsRouter {
330
346
  return {
331
347
  id: randomUUID(),
332
348
  method: wsMsg.method,
333
- path: wsMsg.path,
349
+ path: wsMsg.pathname ?? wsMsg.path,
334
350
  query: { ...(wsMsg.query ?? {}), ...params },
335
351
  body: wsMsg.body,
336
352
  headers: client.headers,
@@ -1,86 +0,0 @@
1
- import { useState, useCallback, useRef } from 'react';
2
- import { ArkErrors } from 'arktype';
3
-
4
- export default function useForm(options) {
5
- const [values, setValues] = useState(options.initialValues);
6
- const [errors, setErrors] = useState({});
7
- const [touched, setTouched] = useState({});
8
- const [isSubmitting, setIsSubmitting] = useState(false);
9
-
10
- const initialRef = useRef(options.initialValues);
11
- const schemaRef = useRef(options.schema);
12
- schemaRef.current = options.schema;
13
- const onSubmitRef = useRef(options.onSubmit);
14
- onSubmitRef.current = options.onSubmit;
15
- const valuesRef = useRef(values);
16
- valuesRef.current = values;
17
-
18
- const isDirty = Object.keys(initialRef.current).some(
19
- (key) => values[key] !== initialRef.current[key],
20
- );
21
-
22
- function setField(name, value) {
23
- setValues((prev) => ({ ...prev, [name]: value }));
24
- setTouched((prev) => ({ ...prev, [name]: true }));
25
- setErrors((prev) => {
26
- if (!prev[name]) return prev;
27
- const next = { ...prev };
28
- delete next[name];
29
- return next;
30
- });
31
- }
32
-
33
- const setError = useCallback((name, message) => {
34
- setErrors((prev) => ({ ...prev, [name]: message }));
35
- }, []);
36
-
37
- const handleSubmit = useCallback(async (e) => {
38
- e?.preventDefault?.();
39
- const currentValues = valuesRef.current;
40
- const schema = schemaRef.current;
41
-
42
- if (schema) {
43
- const result = schema(currentValues);
44
- if (result instanceof ArkErrors) {
45
- const fieldErrors = {};
46
- for (const err of result) {
47
- const key = String(err.path[0]);
48
- if (key && !fieldErrors[key]) {
49
- fieldErrors[key] = err.message;
50
- }
51
- }
52
- setErrors(fieldErrors);
53
- return;
54
- }
55
- }
56
-
57
- setErrors({});
58
- setIsSubmitting(true);
59
- try {
60
- await onSubmitRef.current(currentValues);
61
- } finally {
62
- setIsSubmitting(false);
63
- }
64
- }, []);
65
-
66
- const reset = useCallback((newValues) => {
67
- const resetTo = newValues ?? initialRef.current;
68
- if (newValues) initialRef.current = newValues;
69
- setValues(resetTo);
70
- setErrors({});
71
- setTouched({});
72
- setIsSubmitting(false);
73
- }, []);
74
-
75
- return {
76
- values,
77
- errors,
78
- touched,
79
- isDirty,
80
- isSubmitting,
81
- setField,
82
- setError,
83
- handleSubmit,
84
- reset,
85
- };
86
- }