@solidjs/router 0.15.4 → 0.16.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.
Files changed (56) hide show
  1. package/dist/data/response.d.ts +1 -1
  2. package/dist/index.js +37 -6
  3. package/dist/routers/HashRouter.d.ts +1 -1
  4. package/dist/routers/createRouter.d.ts +1 -1
  5. package/dist/src/components.d.ts +31 -0
  6. package/dist/src/components.jsx +39 -0
  7. package/dist/src/data/action.d.ts +17 -0
  8. package/dist/src/data/action.js +163 -0
  9. package/dist/src/data/action.spec.d.ts +1 -0
  10. package/dist/src/data/action.spec.js +297 -0
  11. package/dist/src/data/createAsync.d.ts +32 -0
  12. package/dist/src/data/createAsync.js +96 -0
  13. package/dist/src/data/createAsync.spec.d.ts +1 -0
  14. package/dist/src/data/createAsync.spec.js +196 -0
  15. package/dist/src/data/events.d.ts +9 -0
  16. package/dist/src/data/events.js +123 -0
  17. package/dist/src/data/events.spec.d.ts +1 -0
  18. package/dist/src/data/events.spec.js +567 -0
  19. package/dist/src/data/index.d.ts +4 -0
  20. package/dist/src/data/index.js +4 -0
  21. package/dist/src/data/query.d.ts +23 -0
  22. package/dist/src/data/query.js +232 -0
  23. package/dist/src/data/query.spec.d.ts +1 -0
  24. package/dist/src/data/query.spec.js +354 -0
  25. package/dist/src/data/response.d.ts +4 -0
  26. package/dist/src/data/response.js +42 -0
  27. package/dist/src/data/response.spec.d.ts +1 -0
  28. package/dist/src/data/response.spec.js +165 -0
  29. package/dist/src/index.d.ts +7 -0
  30. package/dist/src/index.jsx +6 -0
  31. package/dist/src/lifecycle.d.ts +5 -0
  32. package/dist/src/lifecycle.js +69 -0
  33. package/dist/src/routers/HashRouter.d.ts +9 -0
  34. package/dist/src/routers/HashRouter.js +41 -0
  35. package/dist/src/routers/MemoryRouter.d.ts +24 -0
  36. package/dist/src/routers/MemoryRouter.js +57 -0
  37. package/dist/src/routers/Router.d.ts +9 -0
  38. package/dist/src/routers/Router.js +45 -0
  39. package/dist/src/routers/StaticRouter.d.ts +6 -0
  40. package/dist/src/routers/StaticRouter.js +15 -0
  41. package/dist/src/routers/components.d.ts +27 -0
  42. package/dist/src/routers/components.jsx +118 -0
  43. package/dist/src/routers/createRouter.d.ts +10 -0
  44. package/dist/src/routers/createRouter.js +41 -0
  45. package/dist/src/routers/index.d.ts +11 -0
  46. package/dist/src/routers/index.js +6 -0
  47. package/dist/src/routing.d.ts +175 -0
  48. package/dist/src/routing.js +560 -0
  49. package/dist/src/types.d.ts +200 -0
  50. package/dist/src/types.js +1 -0
  51. package/dist/src/utils.d.ts +13 -0
  52. package/dist/src/utils.js +185 -0
  53. package/dist/test/helpers.d.ts +6 -0
  54. package/dist/test/helpers.js +50 -0
  55. package/dist/utils.d.ts +1 -1
  56. package/package.json +1 -1
@@ -0,0 +1,567 @@
1
+ import { createRoot } from "solid-js";
2
+ import { vi } from "vitest";
3
+ import { setupNativeEvents } from "./events.js";
4
+ import { createMockRouter } from "../../test/helpers.js";
5
+ vi.mock("../src/data/action.js", () => ({
6
+ actions: new Map()
7
+ }));
8
+ import { actions } from "./action.js";
9
+ vi.mock("../src/utils.js", () => ({
10
+ mockBase: "https://action"
11
+ }));
12
+ class MockNode {
13
+ nodeName;
14
+ namespaceURI;
15
+ hasAttribute;
16
+ getAttribute;
17
+ href;
18
+ target;
19
+ constructor(tagName, attributes = {}) {
20
+ this.nodeName = tagName.toUpperCase();
21
+ this.namespaceURI = tagName === "a" && attributes.svg ? "http://www.w3.org/2000/svg" : null;
22
+ this.hasAttribute = (name) => name in attributes;
23
+ this.getAttribute = (name) => attributes[name] || null;
24
+ this.href = attributes.href || "";
25
+ this.target = attributes.target || "";
26
+ if (tagName === "a" && attributes.svg) {
27
+ this.href = { baseVal: attributes.href || "" };
28
+ this.target = { baseVal: attributes.target || "" };
29
+ }
30
+ }
31
+ }
32
+ global.Node = MockNode;
33
+ const createMockElement = (tagName, attributes = {}) => {
34
+ return new MockNode(tagName, attributes);
35
+ };
36
+ const createMockEvent = (type, target, options = {}) => {
37
+ return {
38
+ type,
39
+ target,
40
+ defaultPrevented: false,
41
+ button: options.button || 0,
42
+ metaKey: options.metaKey || false,
43
+ altKey: options.altKey || false,
44
+ ctrlKey: options.ctrlKey || false,
45
+ shiftKey: options.shiftKey || false,
46
+ submitter: options.submitter || null,
47
+ preventDefault: vi.fn(),
48
+ composedPath: () => options.path || [target]
49
+ };
50
+ };
51
+ describe("setupNativeEvents", () => {
52
+ let mockRouter;
53
+ let addEventListener;
54
+ let removeEventListener;
55
+ let mockWindow;
56
+ let originalDocument;
57
+ let originalWindow;
58
+ beforeEach(() => {
59
+ mockRouter = createMockRouter();
60
+ addEventListener = vi.fn();
61
+ removeEventListener = vi.fn();
62
+ actions.clear();
63
+ originalDocument = global.document;
64
+ global.document = {
65
+ addEventListener,
66
+ removeEventListener,
67
+ baseURI: "https://example.com/"
68
+ };
69
+ originalWindow = global.window;
70
+ mockWindow = {
71
+ location: { origin: "https://example.com" }
72
+ };
73
+ global.window = mockWindow;
74
+ global.URL = class MockURL {
75
+ origin;
76
+ pathname;
77
+ search;
78
+ hash;
79
+ constructor(url, base) {
80
+ const fullUrl = base ? new URL(url, base).href : url;
81
+ const parsed = new URL(fullUrl);
82
+ this.origin = parsed.origin;
83
+ this.pathname = parsed.pathname;
84
+ this.search = parsed.search;
85
+ this.hash = parsed.hash;
86
+ }
87
+ };
88
+ });
89
+ afterEach(() => {
90
+ global.document = originalDocument;
91
+ global.window = originalWindow;
92
+ vi.clearAllMocks();
93
+ });
94
+ test("should set up default event listeners", () => {
95
+ return createRoot(() => {
96
+ setupNativeEvents()(mockRouter);
97
+ expect(addEventListener).toHaveBeenCalledWith("click", expect.any(Function));
98
+ expect(addEventListener).toHaveBeenCalledWith("submit", expect.any(Function));
99
+ expect(addEventListener).toHaveBeenCalledWith("mousemove", expect.any(Function), {
100
+ passive: true
101
+ });
102
+ expect(addEventListener).toHaveBeenCalledWith("focusin", expect.any(Function), {
103
+ passive: true
104
+ });
105
+ expect(addEventListener).toHaveBeenCalledWith("touchstart", expect.any(Function), {
106
+ passive: true
107
+ });
108
+ });
109
+ });
110
+ test("should skip preload listeners when preload disabled", () => {
111
+ return createRoot(() => {
112
+ setupNativeEvents({ preload: false })(mockRouter);
113
+ expect(addEventListener).toHaveBeenCalledWith("click", expect.any(Function));
114
+ expect(addEventListener).toHaveBeenCalledWith("submit", expect.any(Function));
115
+ expect(addEventListener).not.toHaveBeenCalledWith("mousemove", expect.any(Function), {
116
+ passive: true
117
+ });
118
+ expect(addEventListener).not.toHaveBeenCalledWith("focusin", expect.any(Function), {
119
+ passive: true
120
+ });
121
+ expect(addEventListener).not.toHaveBeenCalledWith("touchstart", expect.any(Function), {
122
+ passive: true
123
+ });
124
+ });
125
+ });
126
+ test("should clean up event listeners on cleanup", () => {
127
+ return createRoot(dispose => {
128
+ setupNativeEvents()(mockRouter);
129
+ dispose();
130
+ expect(removeEventListener).toHaveBeenCalledWith("click", expect.any(Function));
131
+ expect(removeEventListener).toHaveBeenCalledWith("submit", expect.any(Function));
132
+ expect(removeEventListener).toHaveBeenCalledWith("mousemove", expect.any(Function));
133
+ expect(removeEventListener).toHaveBeenCalledWith("focusin", expect.any(Function));
134
+ expect(removeEventListener).toHaveBeenCalledWith("touchstart", expect.any(Function));
135
+ });
136
+ });
137
+ });
138
+ describe("anchor link handling", () => {
139
+ let mockRouter;
140
+ let clickHandler;
141
+ let originalDocument;
142
+ let originalWindow;
143
+ beforeEach(() => {
144
+ mockRouter = createMockRouter();
145
+ originalDocument = global.document;
146
+ global.document = {
147
+ addEventListener: (type, handler) => {
148
+ if (type === "click")
149
+ clickHandler = handler;
150
+ },
151
+ removeEventListener: vi.fn(),
152
+ baseURI: "https://example.com/"
153
+ };
154
+ originalWindow = global.window;
155
+ global.window = {
156
+ location: { origin: "https://example.com" }
157
+ };
158
+ global.URL = class MockURL {
159
+ origin;
160
+ pathname;
161
+ search;
162
+ hash;
163
+ constructor(url) {
164
+ if (url.startsWith("/")) {
165
+ this.origin = "https://example.com";
166
+ this.pathname = url;
167
+ this.search = "";
168
+ this.hash = "";
169
+ }
170
+ else if (url.startsWith("https://example.com")) {
171
+ this.origin = "https://example.com";
172
+ this.pathname = url.replace("https://example.com", "") || "/";
173
+ this.search = "";
174
+ this.hash = "";
175
+ }
176
+ else {
177
+ this.origin = "https://other.com";
178
+ this.pathname = "/";
179
+ this.search = "";
180
+ this.hash = "";
181
+ }
182
+ }
183
+ };
184
+ });
185
+ afterEach(() => {
186
+ global.document = originalDocument;
187
+ global.window = originalWindow;
188
+ });
189
+ test("should handle internal link clicks", () => {
190
+ return createRoot(() => {
191
+ const navigateFromRoute = vi.fn();
192
+ mockRouter.navigatorFactory = () => navigateFromRoute;
193
+ setupNativeEvents()(mockRouter);
194
+ const link = createMockElement("a", { href: "/test-page" });
195
+ const event = createMockEvent("click", link, { path: [link] });
196
+ clickHandler(event);
197
+ expect(event.preventDefault).toHaveBeenCalled();
198
+ expect(navigateFromRoute).toHaveBeenCalledWith("/test-page", {
199
+ resolve: false,
200
+ replace: false,
201
+ scroll: true,
202
+ state: undefined
203
+ });
204
+ });
205
+ });
206
+ test("should ignore external link clicks", () => {
207
+ return createRoot(() => {
208
+ setupNativeEvents()(mockRouter);
209
+ const link = createMockElement("a", { href: "https://external.com/page" });
210
+ const event = createMockEvent("click", link, { path: [link] });
211
+ clickHandler(event);
212
+ expect(event.preventDefault).not.toHaveBeenCalled();
213
+ });
214
+ });
215
+ test("should ignore clicks with modifier keys", () => {
216
+ return createRoot(() => {
217
+ setupNativeEvents()(mockRouter);
218
+ const link = createMockElement("a", { href: "/test-page" });
219
+ const event = createMockEvent("click", link, {
220
+ path: [link],
221
+ metaKey: true
222
+ });
223
+ clickHandler(event);
224
+ expect(event.preventDefault).not.toHaveBeenCalled();
225
+ });
226
+ });
227
+ /**
228
+ * @todo ?
229
+ */
230
+ test("should ignore non-zero button clicks", () => {
231
+ return createRoot(() => {
232
+ setupNativeEvents()(mockRouter);
233
+ const link = createMockElement("a", { href: "/test-page" });
234
+ const event = createMockEvent("click", link, {
235
+ path: [link],
236
+ button: 1
237
+ });
238
+ clickHandler(event);
239
+ expect(event.preventDefault).not.toHaveBeenCalled();
240
+ });
241
+ });
242
+ test("should handle replace attribute", () => {
243
+ return createRoot(() => {
244
+ const navigateFromRoute = vi.fn();
245
+ mockRouter.navigatorFactory = () => navigateFromRoute;
246
+ setupNativeEvents()(mockRouter);
247
+ const link = createMockElement("a", { href: "/test-page", replace: "true" });
248
+ const event = createMockEvent("click", link, { path: [link] });
249
+ clickHandler(event);
250
+ expect(navigateFromRoute).toHaveBeenCalledWith("/test-page", {
251
+ resolve: false,
252
+ replace: true,
253
+ scroll: true,
254
+ state: undefined
255
+ });
256
+ });
257
+ });
258
+ test("should handle noscroll attribute", () => {
259
+ return createRoot(() => {
260
+ const navigateFromRoute = vi.fn();
261
+ mockRouter.navigatorFactory = () => navigateFromRoute;
262
+ setupNativeEvents()(mockRouter);
263
+ const link = createMockElement("a", { href: "/test-page", noscroll: "true" });
264
+ const event = createMockEvent("click", link, { path: [link] });
265
+ clickHandler(event);
266
+ expect(navigateFromRoute).toHaveBeenCalledWith("/test-page", {
267
+ resolve: false,
268
+ replace: false,
269
+ scroll: false,
270
+ state: undefined
271
+ });
272
+ });
273
+ });
274
+ test("should handle state attribute", () => {
275
+ return createRoot(() => {
276
+ const navigateFromRoute = vi.fn();
277
+ mockRouter.navigatorFactory = () => navigateFromRoute;
278
+ setupNativeEvents()(mockRouter);
279
+ const stateData = '{"key":"value"}';
280
+ const link = createMockElement("a", { href: "/test-page", state: stateData });
281
+ const event = createMockEvent("click", link, { path: [link] });
282
+ clickHandler(event);
283
+ expect(navigateFromRoute).toHaveBeenCalledWith("/test-page", {
284
+ resolve: false,
285
+ replace: false,
286
+ scroll: true,
287
+ state: { key: "value" }
288
+ });
289
+ });
290
+ });
291
+ /**
292
+ * @todo ?
293
+ */
294
+ test("should handle SVG links", () => {
295
+ return createRoot(() => {
296
+ const navigateFromRoute = vi.fn();
297
+ mockRouter.navigatorFactory = () => navigateFromRoute;
298
+ setupNativeEvents()(mockRouter);
299
+ const link = createMockElement("a", { href: "/test-page", svg: "true" });
300
+ const event = createMockEvent("click", link, { path: [link] });
301
+ clickHandler(event);
302
+ expect(event.preventDefault).toHaveBeenCalled();
303
+ expect(navigateFromRoute).toHaveBeenCalledWith("/test-page", {
304
+ resolve: false,
305
+ replace: false,
306
+ scroll: true,
307
+ state: undefined
308
+ });
309
+ });
310
+ });
311
+ test("should ignore links with download attribute", () => {
312
+ return createRoot(() => {
313
+ setupNativeEvents()(mockRouter);
314
+ const link = createMockElement("a", { href: "/test-page", download: "file.pdf" });
315
+ const event = createMockEvent("click", link, { path: [link] });
316
+ clickHandler(event);
317
+ expect(event.preventDefault).not.toHaveBeenCalled();
318
+ });
319
+ });
320
+ test("should ignore links with external rel", () => {
321
+ return createRoot(() => {
322
+ setupNativeEvents()(mockRouter);
323
+ const link = createMockElement("a", { href: "/test-page", rel: "external" });
324
+ const event = createMockEvent("click", link, { path: [link] });
325
+ clickHandler(event);
326
+ expect(event.preventDefault).not.toHaveBeenCalled();
327
+ });
328
+ });
329
+ test("should ignore links with target", () => {
330
+ return createRoot(() => {
331
+ setupNativeEvents()(mockRouter);
332
+ const link = createMockElement("a", { href: "/test-page", target: "_blank" });
333
+ const event = createMockEvent("click", link, { path: [link] });
334
+ clickHandler(event);
335
+ expect(event.preventDefault).not.toHaveBeenCalled();
336
+ });
337
+ });
338
+ /**
339
+ * @todo ?
340
+ */
341
+ test("should require `link` attribute when `explicitLinks` enabled", () => {
342
+ return createRoot(() => {
343
+ // Reset with explicitLinks enabled
344
+ setupNativeEvents({ preload: true, explicitLinks: true })(mockRouter);
345
+ const link = createMockElement("a", { href: "/test-page" });
346
+ const event = createMockEvent("click", link, { path: [link] });
347
+ clickHandler(event);
348
+ expect(event.preventDefault).not.toHaveBeenCalled();
349
+ });
350
+ });
351
+ test("should handle links with `link` attribute when `explicitLinks` enabled", () => {
352
+ return createRoot(() => {
353
+ const navigateFromRoute = vi.fn();
354
+ mockRouter.navigatorFactory = () => navigateFromRoute;
355
+ // Reset with explicitLinks enabled
356
+ setupNativeEvents({ preload: true, explicitLinks: true })(mockRouter);
357
+ const link = createMockElement("a", { href: "/test-page", link: "true" });
358
+ const event = createMockEvent("click", link, { path: [link] });
359
+ clickHandler(event);
360
+ expect(event.preventDefault).toHaveBeenCalled();
361
+ expect(navigateFromRoute).toHaveBeenCalled();
362
+ });
363
+ });
364
+ });
365
+ describe("form submit handling", () => {
366
+ let mockRouter;
367
+ let submitHandler;
368
+ let originalDocument;
369
+ let disposeEvents;
370
+ beforeEach(() => {
371
+ mockRouter = createMockRouter();
372
+ actions.clear();
373
+ originalDocument = global.document;
374
+ global.document = {
375
+ addEventListener: (type, handler) => {
376
+ if (type === "submit")
377
+ submitHandler = handler;
378
+ },
379
+ removeEventListener: vi.fn()
380
+ };
381
+ global.URL = class MockURL {
382
+ pathname;
383
+ search;
384
+ constructor(url, base) {
385
+ this.pathname = url.startsWith("/") ? url : "/action";
386
+ this.search = "";
387
+ }
388
+ };
389
+ disposeEvents = createRoot(dispose => {
390
+ setupNativeEvents()(mockRouter);
391
+ return dispose;
392
+ });
393
+ });
394
+ afterEach(() => {
395
+ disposeEvents?.();
396
+ global.document = originalDocument;
397
+ });
398
+ test("handle action form submission", () => {
399
+ return createRoot(() => {
400
+ const mockActionFn = vi.fn();
401
+ const mockAction = {
402
+ url: "https://action/test-action",
403
+ with: vi.fn(),
404
+ call: mockActionFn
405
+ };
406
+ actions.set("https://action/test-action", mockAction);
407
+ const form = {
408
+ getAttribute: (name) => (name === "action" ? "https://action/test-action" : null),
409
+ method: "POST",
410
+ enctype: "application/x-www-form-urlencoded"
411
+ };
412
+ const event = {
413
+ defaultPrevented: false,
414
+ target: form,
415
+ submitter: null,
416
+ preventDefault: vi.fn()
417
+ };
418
+ // Mock FormData and URLSearchParams
419
+ global.FormData = vi.fn(() => ({}));
420
+ global.URLSearchParams = vi.fn(() => ({}));
421
+ submitHandler(event);
422
+ expect(event.preventDefault).toHaveBeenCalled();
423
+ expect(mockActionFn).toHaveBeenCalledWith({ r: mockRouter, f: form }, {});
424
+ });
425
+ });
426
+ /**
427
+ * @todo ?
428
+ */
429
+ test("handle multipart form data", () => {
430
+ return createRoot(() => {
431
+ const mockActionFn = vi.fn();
432
+ const mockAction = {
433
+ url: "https://action/test-action",
434
+ with: vi.fn(),
435
+ call: mockActionFn
436
+ };
437
+ actions.set("https://action/test-action", mockAction);
438
+ const form = {
439
+ getAttribute: (name) => (name === "action" ? "https://action/test-action" : null),
440
+ method: "POST",
441
+ enctype: "multipart/form-data"
442
+ };
443
+ const event = {
444
+ defaultPrevented: false,
445
+ target: form,
446
+ submitter: null,
447
+ preventDefault: vi.fn()
448
+ };
449
+ const mockFormData = {};
450
+ global.FormData = vi.fn(() => mockFormData);
451
+ submitHandler(event);
452
+ expect(event.preventDefault).toHaveBeenCalled();
453
+ expect(mockActionFn).toHaveBeenCalledWith({ r: mockRouter, f: form }, mockFormData);
454
+ });
455
+ });
456
+ test("Throw when using a `GET` action", () => {
457
+ return createRoot(() => {
458
+ const form = {
459
+ getAttribute: () => "https://action/test-action",
460
+ method: "GET"
461
+ };
462
+ const event = {
463
+ defaultPrevented: false,
464
+ target: form,
465
+ submitter: null,
466
+ preventDefault: vi.fn()
467
+ };
468
+ expect(() => submitHandler(event)).toThrow("Only POST forms are supported for Actions");
469
+ });
470
+ });
471
+ test("Throw when using a `PATCH` action", () => {
472
+ return createRoot(() => {
473
+ const form = {
474
+ getAttribute: () => "https://action/test-action",
475
+ method: "PATCH"
476
+ };
477
+ const event = {
478
+ defaultPrevented: false,
479
+ target: form,
480
+ submitter: null,
481
+ preventDefault: vi.fn()
482
+ };
483
+ expect(() => submitHandler(event)).toThrow("Only POST forms are supported for Actions");
484
+ });
485
+ });
486
+ test("Throw when using a `DELETE` action", () => {
487
+ return createRoot(() => {
488
+ const form = {
489
+ getAttribute: () => "https://action/test-action",
490
+ method: "DELETE"
491
+ };
492
+ const event = {
493
+ defaultPrevented: false,
494
+ target: form,
495
+ submitter: null,
496
+ preventDefault: vi.fn()
497
+ };
498
+ expect(() => submitHandler(event)).toThrow("Only POST forms are supported for Actions");
499
+ });
500
+ });
501
+ test("ignore forms without action handlers", () => {
502
+ return createRoot(() => {
503
+ const form = {
504
+ getAttribute: () => "https://action/unknown-action",
505
+ method: "POST"
506
+ };
507
+ const event = {
508
+ defaultPrevented: false,
509
+ target: form,
510
+ submitter: null,
511
+ preventDefault: vi.fn()
512
+ };
513
+ submitHandler(event);
514
+ expect(event.preventDefault).not.toHaveBeenCalled();
515
+ });
516
+ });
517
+ test("handle submitter formaction", () => {
518
+ return createRoot(() => {
519
+ const mockActionFn = vi.fn();
520
+ const mockAction = {
521
+ url: "https://action/submitter-action",
522
+ with: vi.fn(),
523
+ call: mockActionFn
524
+ };
525
+ actions.set("https://action/submitter-action", mockAction);
526
+ const form = {
527
+ getAttribute: () => "https://action/form-action",
528
+ method: "POST"
529
+ };
530
+ const submitter = {
531
+ hasAttribute: (name) => name === "formaction",
532
+ getAttribute: (name) => name === "formaction" ? "https://action/submitter-action" : null
533
+ };
534
+ const event = {
535
+ defaultPrevented: false,
536
+ target: form,
537
+ submitter,
538
+ preventDefault: vi.fn()
539
+ };
540
+ global.FormData = vi.fn(() => ({}));
541
+ global.URLSearchParams = vi.fn(() => ({}));
542
+ submitHandler(event);
543
+ expect(event.preventDefault).toHaveBeenCalled();
544
+ expect(mockActionFn).toHaveBeenCalled();
545
+ });
546
+ });
547
+ /**
548
+ * @todo ?
549
+ */
550
+ test("ignore forms with different action base", () => {
551
+ return createRoot(() => {
552
+ mockRouter.parsePath = path => path;
553
+ const form = {
554
+ getAttribute: () => "/different-base/action",
555
+ method: "POST"
556
+ };
557
+ const event = {
558
+ defaultPrevented: false,
559
+ target: form,
560
+ submitter: null,
561
+ preventDefault: vi.fn()
562
+ };
563
+ submitHandler(event);
564
+ expect(event.preventDefault).not.toHaveBeenCalled();
565
+ });
566
+ });
567
+ });
@@ -0,0 +1,4 @@
1
+ export { createAsync, createAsyncStore, type AccessorWithLatest } from "./createAsync.js";
2
+ export { action, useSubmission, useSubmissions, useAction, type Action } from "./action.js";
3
+ export { query, revalidate, cache, type CachedFunction } from "./query.js";
4
+ export { redirect, reload, json } from "./response.js";
@@ -0,0 +1,4 @@
1
+ export { createAsync, createAsyncStore } from "./createAsync.js";
2
+ export { action, useSubmission, useSubmissions, useAction } from "./action.js";
3
+ export { query, revalidate, cache } from "./query.js";
4
+ export { redirect, reload, json } from "./response.js";
@@ -0,0 +1,23 @@
1
+ import type { CacheEntry, NarrowResponse } from "../types.js";
2
+ /**
3
+ * Revalidates the given cache entry/entries.
4
+ */
5
+ export declare function revalidate(key?: string | string[] | void, force?: boolean): Promise<void>;
6
+ export declare function cacheKeyOp(key: string | string[] | void, fn: (cacheEntry: CacheEntry) => void): void;
7
+ export type CachedFunction<T extends (...args: any) => any> = T extends (...args: infer A) => infer R ? ([] extends {
8
+ [K in keyof A]-?: A[K];
9
+ } ? (...args: never[]) => R extends Promise<infer P> ? Promise<NarrowResponse<P>> : NarrowResponse<R> : (...args: A) => R extends Promise<infer P> ? Promise<NarrowResponse<P>> : NarrowResponse<R>) & {
10
+ keyFor: (...args: A) => string;
11
+ key: string;
12
+ } : never;
13
+ export declare function query<T extends (...args: any) => any>(fn: T, name: string): CachedFunction<T>;
14
+ export declare namespace query {
15
+ export var get: (key: string) => any;
16
+ export var set: <T>(key: string, value: T extends Promise<any> ? never : T) => void;
17
+ var _a: (key: string) => boolean;
18
+ export var clear: () => void;
19
+ export { _a as delete };
20
+ }
21
+ /** @deprecated use query instead */
22
+ export declare const cache: typeof query;
23
+ export declare function hashKey<T extends Array<any>>(args: T): string;