@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 +2 -3
- package/dist/data/cache.d.ts +4 -5
- package/dist/data/cache.js +6 -11
- package/dist/data/createAsync.d.ts +15 -2
- package/dist/data/createAsync.js +30 -5
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +1 -1
- package/dist/index.js +31 -11
- package/dist/routers/MemoryRouter.d.ts +3 -0
- package/dist/routers/MemoryRouter.js +2 -0
- package/dist/routers/components.d.ts +1 -1
- package/dist/routers/components.jsx +1 -1
- package/package.json +1 -1
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
|
|
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";
|
package/dist/data/cache.d.ts
CHANGED
|
@@ -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) =>
|
|
6
|
-
keyFor: (...args:
|
|
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) =>
|
|
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;
|
package/dist/data/cache.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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>;
|
package/dist/data/createAsync.js
CHANGED
|
@@ -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
|
-
|
|
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;
|
package/dist/data/index.d.ts
CHANGED
|
@@ -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";
|
package/dist/data/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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}>
|