@solidjs/router 0.11.4 → 0.12.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/README.md CHANGED
@@ -29,7 +29,6 @@ It supports all of Solid's SSR methods and has Solid's transitions baked in, so
29
29
  - [useLocation](#uselocation)
30
30
  - [useSearchParams](#usesearchparams)
31
31
  - [useIsRouting](#useisrouting)
32
- - [useRouteData](#useroutedata)
33
32
  - [useMatch](#usematch)
34
33
  - [useBeforeLeave](#usebeforeleave)
35
34
  - [SPAs in Deployed Environments](#spas-in-deployed-environments)
@@ -490,7 +489,7 @@ You can revalidate the cache using the `revalidate` method or you can set `reval
490
489
  This is light wrapper over `createResource` that aims to serve as stand-in for a future primitive we intend to bring to Solid core in 2.0. It is a simpler async primitive where the function tracks like `createMemo` and it expects a promise back that it turns into a Signal. Reading it before it is ready causes Suspense/Transitions to trigger.
491
490
 
492
491
  ```jsx
493
- const user = createAsync(() => getUser(params.id))
492
+ const user = createAsync((currentValue) => getUser(params.id))
494
493
  ```
495
494
 
496
495
  Using `cache` in `createResource` directly won't work properly as the fetcher is not reactive and it won't invalidate properly.
@@ -674,7 +673,7 @@ render(() => <Router>{route}</Router>, document.getElementById("app"));
674
673
 
675
674
  ### Hash Mode Router
676
675
 
677
- By default, Solid Router uses `location.pathname` as route path. You can simply switch to hash mode through the `source` property on `<Router>` component.
676
+ By default, Solid Router uses `location.pathname` as route path. You can simply switch to hash mode through using `<HashRouter>`.
678
677
 
679
678
  ```jsx
680
679
  import { HashRouter } from "@solidjs/router";
@@ -1,12 +1,11 @@
1
- import { type ReconcileOptions } from "solid-js/store";
2
1
  import { CacheEntry } from "../types.js";
3
2
  export declare function revalidate(key?: string | string[] | void, force?: boolean): Promise<void>;
4
3
  export declare function cacheKeyOp(key: string | string[] | void, fn: (cacheEntry: CacheEntry) => void): void;
5
- export type CachedFunction<T extends (...args: any) => U | Response, U> = T & {
6
- keyFor: (...args: Parameters<T>) => string;
4
+ export type CachedFunction<T extends (...args: any) => any> = T extends (...args: infer A) => infer R ? ([] extends A ? (...args: never[]) => R : T) & {
5
+ keyFor: (...args: A) => string;
7
6
  key: string;
8
- };
9
- export declare function cache<T extends (...args: any) => U | Response, U>(fn: T, name: string, options?: ReconcileOptions): CachedFunction<T, U>;
7
+ } : never;
8
+ export declare function cache<T extends (...args: any) => any>(fn: T, name: string): CachedFunction<T>;
10
9
  export declare namespace cache {
11
10
  var set: (key: string, value: any) => void;
12
11
  var clear: () => void;
@@ -1,5 +1,4 @@
1
1
  import { createSignal, getListener, getOwner, onCleanup, sharedConfig, startTransition } from "solid-js";
2
- import { createStore, reconcile } from "solid-js/store";
3
2
  import { getRequestEvent, isServer } from "solid-js/web";
4
3
  import { useNavigate, getIntent } from "../routing.js";
5
4
  const LocationHeader = "Location";
@@ -41,8 +40,7 @@ export function cacheKeyOp(key, fn) {
41
40
  fn(cacheMap.get(k));
42
41
  }
43
42
  }
44
- export function cache(fn, name, options) {
45
- const [store, setStore] = createStore({});
43
+ export function cache(fn, name) {
46
44
  // prioritize GET for server functions
47
45
  if (fn.GET)
48
46
  fn = fn.GET;
@@ -89,8 +87,8 @@ export function cache(fn, name, options) {
89
87
  let res = cached[1];
90
88
  if (intent !== "preload") {
91
89
  res =
92
- "then" in cached[1]
93
- ? cached[1].then(handleResponse(false), handleResponse(true))
90
+ "then" in (cached[1])
91
+ ? (cached[1]).then(handleResponse(false), handleResponse(true))
94
92
  : handleResponse(false)(cached[1]);
95
93
  !isServer && intent === "navigate" && startTransition(() => cached[3][1](cached[0])); // update version
96
94
  }
@@ -124,8 +122,8 @@ export function cache(fn, name, options) {
124
122
  }
125
123
  if (intent !== "preload") {
126
124
  res =
127
- "then" in res
128
- ? res.then(handleResponse(false), handleResponse(true))
125
+ "then" in (res)
126
+ ? (res).then(handleResponse(false), handleResponse(true))
129
127
  : handleResponse(false)(res);
130
128
  }
131
129
  return res;
@@ -153,10 +151,7 @@ export function cache(fn, name, options) {
153
151
  }
154
152
  if (error)
155
153
  throw v;
156
- if (isServer)
157
- return v;
158
- setStore(key, reconcile(v, options));
159
- return store[key];
154
+ return v;
160
155
  };
161
156
  }
162
157
  });
@@ -2,13 +2,26 @@
2
2
  * This is mock of the eventual Solid 2.0 primitive. It is not fully featured.
3
3
  */
4
4
  import { type Accessor } from "solid-js";
5
- export declare function createAsync<T>(fn: () => Promise<T>, options: {
5
+ import { type ReconcileOptions } from "solid-js/store";
6
+ export declare function createAsync<T>(fn: (prev: T) => Promise<T>, options: {
6
7
  name?: string;
7
8
  initialValue: T;
8
9
  deferStream?: boolean;
9
10
  }): Accessor<T>;
10
- export declare function createAsync<T>(fn: () => Promise<T>, options?: {
11
+ export declare function createAsync<T>(fn: (prev: T | undefined) => Promise<T>, options?: {
11
12
  name?: string;
12
13
  initialValue?: T;
13
14
  deferStream?: boolean;
14
15
  }): Accessor<T | undefined>;
16
+ export declare function createAsyncStore<T>(fn: (prev: T) => Promise<T>, options: {
17
+ name?: string;
18
+ initialValue: T;
19
+ deferStream?: boolean;
20
+ reconcile?: ReconcileOptions;
21
+ }): Accessor<T>;
22
+ export declare function createAsyncStore<T>(fn: (prev: T | undefined) => Promise<T>, options?: {
23
+ name?: string;
24
+ initialValue?: T;
25
+ deferStream?: boolean;
26
+ reconcile?: ReconcileOptions;
27
+ }): Accessor<T | undefined>;
@@ -1,12 +1,37 @@
1
1
  /**
2
2
  * This is mock of the eventual Solid 2.0 primitive. It is not fully featured.
3
3
  */
4
- import { createResource, sharedConfig } from "solid-js";
4
+ import { createResource, sharedConfig, untrack } from "solid-js";
5
+ import { createStore, reconcile, unwrap } from "solid-js/store";
5
6
  import { isServer } from "solid-js/web";
6
7
  export function createAsync(fn, options) {
7
- const [resource] = createResource(() => subFetch(fn), v => v, options);
8
+ let resource;
9
+ let prev = () => !resource || resource.state === "unresolved" ? undefined : resource.latest;
10
+ [resource] = createResource(() => subFetch(fn, untrack(prev)), v => v, options);
8
11
  return () => resource();
9
12
  }
13
+ export function createAsyncStore(fn, options = {}) {
14
+ let resource;
15
+ let prev = () => !resource || resource.state === "unresolved" ? undefined : unwrap(resource.latest);
16
+ [resource] = createResource(() => subFetch(fn, untrack(prev)), v => v, {
17
+ ...options,
18
+ storage: (init) => createDeepSignal(init, options.reconcile)
19
+ });
20
+ return () => resource();
21
+ }
22
+ function createDeepSignal(value, options) {
23
+ const [store, setStore] = createStore({
24
+ value
25
+ });
26
+ return [
27
+ () => store.value,
28
+ (v) => {
29
+ typeof v === "function" && (v = v());
30
+ setStore("value", reconcile(v, options));
31
+ return store.value;
32
+ }
33
+ ];
34
+ }
10
35
  // mock promise while hydrating to prevent fetching
11
36
  class MockPromise {
12
37
  static all() {
@@ -37,15 +62,15 @@ class MockPromise {
37
62
  return new MockPromise();
38
63
  }
39
64
  }
40
- function subFetch(fn) {
65
+ function subFetch(fn, prev) {
41
66
  if (isServer || !sharedConfig.context)
42
- return fn();
67
+ return fn(prev);
43
68
  const ogFetch = fetch;
44
69
  const ogPromise = Promise;
45
70
  try {
46
71
  window.fetch = () => new MockPromise();
47
72
  Promise = MockPromise;
48
- return fn();
73
+ return fn(prev);
49
74
  }
50
75
  finally {
51
76
  window.fetch = ogFetch;
@@ -1,4 +1,4 @@
1
- export { createAsync } from "./createAsync.js";
1
+ export { createAsync, createAsyncStore } from "./createAsync.js";
2
2
  export { action, useSubmission, useSubmissions, useAction, type Action } from "./action.js";
3
3
  export { cache, revalidate, type CachedFunction } from "./cache.js";
4
4
  export { redirect, reload, json } from "./response.js";
@@ -1,4 +1,4 @@
1
- export { createAsync } from "./createAsync.js";
1
+ export { createAsync, createAsyncStore } from "./createAsync.js";
2
2
  export { action, useSubmission, useSubmissions, useAction } from "./action.js";
3
3
  export { cache, revalidate } from "./cache.js";
4
4
  export { redirect, reload, json } from "./response.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isServer, getRequestEvent, createComponent as createComponent$1, delegateEvents, spread, mergeProps as mergeProps$1, template } from 'solid-js/web';
2
2
  import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, createSignal, createRenderEffect, on, startTransition, resetErrorBoundaries, createComponent, children, mergeProps, createRoot, Show, getListener, sharedConfig, $TRACK, splitProps, createResource } from 'solid-js';
3
- import { createStore, reconcile } from 'solid-js/store';
3
+ import { createStore, reconcile, unwrap } from 'solid-js/store';
4
4
 
5
5
  function createBeforeLeave() {
6
6
  let listeners = new Set();
@@ -641,6 +641,7 @@ const createRouterComponent = router => props => {
641
641
  const routeDefs = children(() => props.children);
642
642
  const branches = createMemo(() => createBranches(props.root ? {
643
643
  component: props.root,
644
+ load: props.rootLoad,
644
645
  children: routeDefs()
645
646
  } : routeDefs(), props.base || ""));
646
647
  const routerState = createRouterContext(router, branches, {
@@ -878,8 +879,7 @@ function cacheKeyOp(key, fn) {
878
879
  if (key === undefined || matchKey(k, key)) fn(cacheMap.get(k));
879
880
  }
880
881
  }
881
- function cache(fn, name, options) {
882
- const [store, setStore] = createStore({});
882
+ function cache(fn, name) {
883
883
  // prioritize GET for server functions
884
884
  if (fn.GET) fn = fn.GET;
885
885
  const cachedFn = (...args) => {
@@ -971,9 +971,7 @@ function cache(fn, name, options) {
971
971
  if (v.customBody) v = await v.customBody();
972
972
  }
973
973
  if (error) throw v;
974
- if (isServer) return v;
975
- setStore(key, reconcile(v, options));
976
- return store[key];
974
+ return v;
977
975
  };
978
976
  }
979
977
  };
@@ -1373,6 +1371,7 @@ function MemoryRouter(props) {
1373
1371
  get: memoryHistory.get,
1374
1372
  set: memoryHistory.set,
1375
1373
  init: memoryHistory.listen,
1374
+ create: setupNativeEvents(props.preload, props.explicitLinks, props.actionBase),
1376
1375
  utils: {
1377
1376
  go: memoryHistory.go
1378
1377
  }
@@ -1445,9 +1444,30 @@ function Navigate(props) {
1445
1444
  * This is mock of the eventual Solid 2.0 primitive. It is not fully featured.
1446
1445
  */
1447
1446
  function createAsync(fn, options) {
1448
- const [resource] = createResource(() => subFetch(fn), v => v, options);
1447
+ let resource;
1448
+ let prev = () => !resource || resource.state === "unresolved" ? undefined : resource.latest;
1449
+ [resource] = createResource(() => subFetch(fn, untrack(prev)), v => v, options);
1450
+ return () => resource();
1451
+ }
1452
+ function createAsyncStore(fn, options = {}) {
1453
+ let resource;
1454
+ let prev = () => !resource || resource.state === "unresolved" ? undefined : unwrap(resource.latest);
1455
+ [resource] = createResource(() => subFetch(fn, untrack(prev)), v => v, {
1456
+ ...options,
1457
+ storage: init => createDeepSignal(init, options.reconcile)
1458
+ });
1449
1459
  return () => resource();
1450
1460
  }
1461
+ function createDeepSignal(value, options) {
1462
+ const [store, setStore] = createStore({
1463
+ value
1464
+ });
1465
+ return [() => store.value, v => {
1466
+ typeof v === "function" && (v = v());
1467
+ setStore("value", reconcile(v, options));
1468
+ return store.value;
1469
+ }];
1470
+ }
1451
1471
 
1452
1472
  // mock promise while hydrating to prevent fetching
1453
1473
  class MockPromise {
@@ -1479,14 +1499,14 @@ class MockPromise {
1479
1499
  return new MockPromise();
1480
1500
  }
1481
1501
  }
1482
- function subFetch(fn) {
1483
- if (isServer || !sharedConfig.context) return fn();
1502
+ function subFetch(fn, prev) {
1503
+ if (isServer || !sharedConfig.context) return fn(prev);
1484
1504
  const ogFetch = fetch;
1485
1505
  const ogPromise = Promise;
1486
1506
  try {
1487
1507
  window.fetch = () => new MockPromise();
1488
1508
  Promise = MockPromise;
1489
- return fn();
1509
+ return fn(prev);
1490
1510
  } finally {
1491
1511
  window.fetch = ogFetch;
1492
1512
  Promise = ogPromise;
@@ -1546,4 +1566,4 @@ function json(data, init = {}) {
1546
1566
  return response;
1547
1567
  }
1548
1568
 
1549
- export { A, HashRouter, MemoryRouter, Navigate, Route, Router, StaticRouter, mergeSearchString as _mergeSearchString, action, cache, createAsync, createBeforeLeave, createMemoryHistory, createRouter, json, keepDepth, notifyIfNotBlocked, redirect, reload, revalidate, saveCurrentDepth, useAction, useBeforeLeave, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, useResolvedPath, useSearchParams, useSubmission, useSubmissions };
1569
+ export { A, HashRouter, MemoryRouter, Navigate, Route, Router, StaticRouter, mergeSearchString as _mergeSearchString, action, cache, createAsync, createAsyncStore, createBeforeLeave, createMemoryHistory, createRouter, json, keepDepth, notifyIfNotBlocked, redirect, reload, revalidate, saveCurrentDepth, useAction, useBeforeLeave, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, useResolvedPath, useSearchParams, useSubmission, useSubmissions };
@@ -17,5 +17,8 @@ export declare function createMemoryHistory(): {
17
17
  };
18
18
  export type MemoryRouterProps = BaseRouterProps & {
19
19
  history?: MemoryHistory;
20
+ actionBase?: string;
21
+ explicitLinks?: boolean;
22
+ preload?: boolean;
20
23
  };
21
24
  export declare function MemoryRouter(props: MemoryRouterProps): JSX.Element;
@@ -1,4 +1,5 @@
1
1
  import { createRouter, scrollToHash } from "./createRouter.js";
2
+ import { setupNativeEvents } from "../data/events.js";
2
3
  export function createMemoryHistory() {
3
4
  const entries = ["/"];
4
5
  let index = 0;
@@ -45,6 +46,7 @@ export function MemoryRouter(props) {
45
46
  get: memoryHistory.get,
46
47
  set: memoryHistory.set,
47
48
  init: memoryHistory.listen,
49
+ create: setupNativeEvents(props.preload, props.explicitLinks, props.actionBase),
48
50
  utils: {
49
51
  go: memoryHistory.go
50
52
  }
@@ -7,7 +7,7 @@ export type BaseRouterProps = {
7
7
  */
8
8
  root?: Component<RouteSectionProps>;
9
9
  rootLoad?: RouteLoadFunc;
10
- singleFlight: boolean;
10
+ singleFlight?: boolean;
11
11
  children?: JSX.Element | RouteDefinition | RouteDefinition[];
12
12
  };
13
13
  export declare const createRouterComponent: (router: RouterIntegration) => (props: BaseRouterProps) => JSX.Element;
@@ -6,7 +6,7 @@ import { createMemoObject, extractSearchParams } from "../utils.js";
6
6
  export const createRouterComponent = (router) => (props) => {
7
7
  const { base } = props;
8
8
  const routeDefs = children(() => props.children);
9
- const branches = createMemo(() => createBranches(props.root ? { component: props.root, children: routeDefs() } : routeDefs(), props.base || ""));
9
+ const branches = createMemo(() => createBranches(props.root ? { component: props.root, load: props.rootLoad, children: routeDefs() } : routeDefs(), props.base || ""));
10
10
  const routerState = createRouterContext(router, branches, { base, singleFlight: props.singleFlight });
11
11
  router.create && router.create(routerState);
12
12
  return (<RouterContextObj.Provider value={routerState}>
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "Ryan Turnquist"
7
7
  ],
8
8
  "license": "MIT",
9
- "version": "0.11.4",
9
+ "version": "0.12.0",
10
10
  "homepage": "https://github.com/solidjs/solid-router#readme",
11
11
  "repository": {
12
12
  "type": "git",