Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@solidjs/router

Package Overview
Dependencies
Maintainers
2
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@solidjs/router - npm Package Compare versions

Comparing version 0.14.10 to 0.15.0

dist/data/query.d.ts

6

dist/data/action.d.ts

@@ -13,2 +13,6 @@ import { JSX } from "solid-js";

export declare function useAction<T extends Array<any>, U, V>(action: Action<T, U, V>): (...args: Parameters<Action<T, U, V>>) => Promise<NarrowResponse<U>>;
export declare function action<T extends Array<any>, U = void>(fn: (...args: T) => Promise<U>, name?: string): Action<T, U, T>;
export declare function action<T extends Array<any>, U = void>(fn: (...args: T) => Promise<U>, name?: string): Action<T, U>;
export declare function action<T extends Array<any>, U = void>(fn: (...args: T) => Promise<U>, options?: {
name?: string;
onComplete?: (s: Submission<T, U>) => boolean;
}): Action<T, U>;

27

dist/data/action.js

@@ -5,3 +5,3 @@ import { $TRACK, createMemo, createSignal, onCleanup, getOwner } from "solid-js";

import { mockBase } from "../utils.js";
import { cacheKeyOp, hashKey, revalidate, cache } from "./cache.js";
import { cacheKeyOp, hashKey, revalidate, query } from "./query.js";
export const actions = /* #__PURE__ */ new Map();

@@ -28,4 +28,4 @@ export function useSubmissions(fn, filter) {

get(_, property) {
if (submissions.length === 0 && property === "clear" || property === "retry")
return (() => { });
if ((submissions.length === 0 && property === "clear") || property === "retry")
return () => { };
return submissions[submissions.length - 1]?.[property];

@@ -39,3 +39,3 @@ }

}
export function action(fn, name) {
export function action(fn, options = {}) {
function mutate(...variables) {

@@ -52,2 +52,14 @@ const router = this.r;

const result = await handleResponse(res, error, router.navigatorFactory());
let retry = null;
!o.onComplete?.({
...submission,
result: result?.data,
error: result?.error,
pending: false,
retry() {
return retry = submission.retry();
}
});
if (retry)
return retry;
if (!result)

@@ -76,3 +88,3 @@ return submission.clear();

clear() {
router.submissions[1](v => v.filter(i => i.input !== variables));
router.submissions[1](v => v.filter(i => i !== submission));
},

@@ -88,4 +100,5 @@ retry() {

}
const o = typeof options === "string" ? { name: options } : options;
const url = fn.url ||
(name && `https://action/${name}`) ||
(o.name && `https://action/${o.name}`) ||
(!isServer ? `https://action/${hashString(fn.toString())}` : "");

@@ -151,3 +164,3 @@ mutate.base = url;

// set cache
flightKeys && flightKeys.forEach(k => cache.set(k, custom[k]));
flightKeys && flightKeys.forEach(k => query.set(k, custom[k]));
// trigger revalidation

@@ -154,0 +167,0 @@ await revalidate(keys, false);

export { createAsync, createAsyncStore, type AccessorWithLatest } from "./createAsync.js";
export { action, useSubmission, useSubmissions, useAction, type Action } from "./action.js";
export { cache, revalidate, type CachedFunction } from "./cache.js";
export { query, revalidate, cache, type CachedFunction } from "./query.js";
export { redirect, reload, json } from "./response.js";
export { createAsync, createAsyncStore } from "./createAsync.js";
export { action, useSubmission, useSubmissions, useAction } from "./action.js";
export { cache, revalidate } from "./cache.js";
export { query, revalidate, cache } from "./query.js";
export { redirect, reload, json } from "./response.js";

@@ -897,3 +897,3 @@ import { isServer, getRequestEvent, createComponent as createComponent$1, memo, delegateEvents, spread, mergeProps as mergeProps$1, template } from 'solid-js/web';

for (let [k, v] of cacheMap.entries()) {
if (!v[3].count && now - v[0] > CACHE_TIMEOUT) {
if (!v[4].count && now - v[0] > CACHE_TIMEOUT) {
cacheMap.delete(k);

@@ -915,3 +915,3 @@ }

force && (entry[0] = 0); //force cache miss
entry[3][1](now); // retrigger live signals
entry[4][1](now); // retrigger live signals
});

@@ -926,3 +926,3 @@ });

}
function cache(fn, name) {
function query(fn, name) {
// prioritize GET for server functions

@@ -956,10 +956,10 @@ if (fn.GET) fn = fn.GET;

tracking = true;
onCleanup(() => cached[3].count--);
onCleanup(() => cached[4].count--);
}
if (cached && cached[0] && (isServer || intent === "native" || cached[3].count || Date.now() - cached[0] < PRELOAD_TIMEOUT)) {
if (cached && cached[0] && (isServer || intent === "native" || cached[4].count || Date.now() - cached[0] < PRELOAD_TIMEOUT)) {
if (tracking) {
cached[3].count++;
cached[3][0](); // track
cached[4].count++;
cached[4][0](); // track
}
if (cached[2] === "preload" && intent !== "preload") {
if (cached[3] === "preload" && intent !== "preload") {
cached[0] = now;

@@ -970,3 +970,3 @@ }

res = "then" in cached[1] ? cached[1].then(handleResponse(false), handleResponse(true)) : handleResponse(false)(cached[1]);
!isServer && intent === "navigate" && startTransition(() => cached[3][1](cached[0])); // update version
!isServer && intent === "navigate" && startTransition(() => cached[4][1](cached[0])); // update version
}

@@ -981,11 +981,11 @@ inPreloadFn && "then" in res && res.catch(() => {});

cached[1] = res;
cached[2] = intent;
!isServer && intent === "navigate" && startTransition(() => cached[3][1](cached[0])); // update version
cached[3] = intent;
!isServer && intent === "navigate" && startTransition(() => cached[4][1](cached[0])); // update version
} else {
cache.set(key, cached = [now, res, intent, createSignal(now)]);
cached[3].count = 0;
cache.set(key, cached = [now, res,, intent, createSignal(now)]);
cached[4].count = 0;
}
if (tracking) {
cached[3].count++;
cached[3][0](); // track
cached[4].count++;
cached[4][0](); // track
}

@@ -1030,2 +1030,3 @@ if (isServer) {

if (error) throw v;
cached[2] = v;
return v;

@@ -1039,3 +1040,7 @@ };

}
cache.set = (key, value) => {
query.get = key => {
const cached = getCache().get(key);
return cached[2];
};
query.set = (key, value) => {
const cache = getCache();

@@ -1046,10 +1051,15 @@ const now = Date.now();

cached[0] = now;
cached[1] = value;
cached[2] = "preload";
cached[1] = Promise.resolve(value);
cached[2] = value;
cached[3] = "preload";
} else {
cache.set(key, cached = [now, value,, createSignal(now)]);
cached[3].count = 0;
cache.set(key, cached = [now, Promise.resolve(value), value, "preload", createSignal(now)]);
cached[4].count = 0;
}
};
cache.clear = () => getCache().clear();
query.delete = key => getCache().delete(key);
query.clear = () => getCache().clear();
/** @deprecated use query instead */
const cache = query;
function matchKey(key, keys) {

@@ -1105,3 +1115,3 @@ for (let k of keys) {

}
function action(fn, name) {
function action(fn, options = {}) {
function mutate(...variables) {

@@ -1120,2 +1130,13 @@ const router = this.r;

const result = await handleResponse(res, error, router.navigatorFactory());
let retry = null;
!o.onComplete?.({
...submission,
result: result?.data,
error: result?.error,
pending: false,
retry() {
return retry = submission.retry();
}
});
if (retry) return retry;
if (!result) return submission.clear();

@@ -1140,3 +1161,3 @@ setResult(result);

clear() {
router.submissions[1](v => v.filter(i => i.input !== variables));
router.submissions[1](v => v.filter(i => i !== submission));
},

@@ -1151,3 +1172,6 @@ retry() {

}
const url = fn.url || name && `https://action/${name}` || (!isServer ? `https://action/${hashString(fn.toString())}` : "");
const o = typeof options === "string" ? {
name: options
} : options;
const url = fn.url || o.name && `https://action/${o.name}` || (!isServer ? `https://action/${hashString(fn.toString())}` : "");
mutate.base = url;

@@ -1207,3 +1231,3 @@ return toAction(mutate, url);

// set cache
flightKeys && flightKeys.forEach(k => cache.set(k, custom[k]));
flightKeys && flightKeys.forEach(k => query.set(k, custom[k]));
// trigger revalidation

@@ -1675,2 +1699,2 @@ await revalidate(keys, false);

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, useCurrentMatches, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, usePreloadRoute, useResolvedPath, useSearchParams, useSubmission, useSubmissions };
export { A, HashRouter, MemoryRouter, Navigate, Route, Router, StaticRouter, mergeSearchString as _mergeSearchString, action, cache, createAsync, createAsyncStore, createBeforeLeave, createMemoryHistory, createRouter, json, keepDepth, notifyIfNotBlocked, query, redirect, reload, revalidate, saveCurrentDepth, useAction, useBeforeLeave, useCurrentMatches, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, usePreloadRoute, useResolvedPath, useSearchParams, useSubmission, useSubmissions };

@@ -186,3 +186,3 @@ import type { Component, JSX, Signal } from "solid-js";

}
export type CacheEntry = [number, any, Intent | undefined, Signal<number> & {
export type CacheEntry = [number, Promise<any>, any, Intent | undefined, Signal<number> & {
count: number;

@@ -189,0 +189,0 @@ }];

@@ -9,3 +9,3 @@ {

"license": "MIT",
"version": "0.14.10",
"version": "0.15.0",
"homepage": "https://github.com/solidjs/solid-router#readme",

@@ -12,0 +12,0 @@ "repository": {

@@ -430,19 +430,19 @@ <p>

### `cache`
### `query`
To prevent duplicate fetching and to trigger handle refetching we provide a cache api. That takes a function and returns the same function.
To prevent duplicate fetching and to trigger handle refetching we provide a query api. That takes a function and returns the same function.
```jsx
const getUser = cache(async (id) => {
const getUser = query(async (id) => {
return (await fetch(`/api/users${id}`)).json()
}, "users") // used as cache key + serialized arguments
}, "users") // used as the query key + serialized arguments
```
It is expected that the arguments to the cache function are serializable.
It is expected that the arguments to the query function are serializable.
This cache accomplishes the following:
This query accomplishes the following:
1. It does just deduping on the server for the lifetime of the request.
2. It does preload cache in the browser which lasts 5 seconds. When a route is preloaded on hover or when preload is called when entering a route it will make sure to dedupe calls.
1. It does deduping on the server for the lifetime of the request.
2. It fills a preload cache in the browser which lasts 5 seconds. When a route is preloaded on hover or when preload is called when entering a route it will make sure to dedupe calls.
3. We have a reactive refetch mechanism based on key. So we can tell routes that aren't new to retrigger on action revalidation.
4. It will serve as a back/forward cache for browser navigation up to 5 mins. Any user based navigation or link click bypasses it. Revalidation or new fetch updates the cache.
4. It will serve as a back/forward cache for browser navigation up to 5 mins. Any user based navigation or link click bypasses this cache. Revalidation or new fetch updates the cache.

@@ -454,3 +454,3 @@ Using it with preload function might look like:

import { Route } from "@solidjs/router";
import { getUser } from ... // the cache function
import { getUser } from ... // the query function

@@ -472,3 +472,3 @@ const User = lazy(() => import("./pages/users/[id].js"));

// pages/users/[id].js
import { getUser } from ... // the cache function
import { getUser } from ... // the query function

@@ -489,5 +489,5 @@ export default function User(props) {

You can revalidate the cache using the `revalidate` method or you can set `revalidate` keys on your response from your actions. If you pass the whole key it will invalidate all the entries for the cache (ie "users" in the example above). You can also invalidate a single entry by using `keyFor`.
You can revalidate the query using the `revalidate` method or you can set `revalidate` keys on your response from your actions. If you pass the whole key it will invalidate all the entries for the query (ie "users" in the example above). You can also invalidate a single entry by using `keyFor`.
`cache` can be defined anywhere and then used inside your components with:
`query` can be defined anywhere and then used inside your components with:

@@ -509,3 +509,3 @@ ### `createAsync`

Using `cache` in `createResource` directly won't work properly as the fetcher is not reactive and it won't invalidate properly.
Using `query` in `createResource` directly won't work properly as the fetcher is not reactive and it won't invalidate properly.

@@ -566,3 +566,5 @@ ### `createAsyncStore`

#### Notes of `<form>` implementation and SSR
Actions also a second argument which can be the name or an option object with `name` and `onComplete`. `name` is used to identify SSR actions that aren't server functions (see note below). `onComplete` allows you to configure behavior when `action`s complete. Keep in mind `onComplete` does not work when JavaScript is disabled.
#### Notes on `<form>` implementation and SSR
This requires stable references as you can only serialize a string as an attribute, and across SSR they'd need to match. The solution is providing a unique name.

@@ -606,3 +608,3 @@

These are used to communicate router navigations from cache/actions, and can include invalidation hints. Generally these are thrown to not interfere the with the types and make it clear that function ends execution at that point.
These are used to communicate router navigations from query/actions, and can include invalidation hints. Generally these are thrown to not interfere the with the types and make it clear that function ends execution at that point.

@@ -613,3 +615,3 @@ #### `redirect(path, options)`

```js
const getUser = cache(() => {
const getUser = query(() => {
const user = await api.getCurrentUser()

@@ -625,3 +627,3 @@ if (!user) throw redirect("/login");

```js
const getTodo = cache(async (id: number) => {
const getTodo = query(async (id: number) => {
const todo = await fetchTodo(id);

@@ -949,3 +951,3 @@ return todo;

These have been replaced by a preload mechanism. This allows link hover preloads (as the preload function can be run as much as wanted without worry about reactivity). It support deduping/cache APIs which give more control over how things are cached. It also addresses TS issues with getting the right types in the Component without `typeof` checks.
These have been replaced by a preload mechanism. This allows link hover preloads (as the preload function can be run as much as wanted without worry about reactivity). It support deduping/query APIs which give more control over how things are cached. It also addresses TS issues with getting the right types in the Component without `typeof` checks.

@@ -952,0 +954,0 @@ That being said you can reproduce the old pattern largely by turning off preloads at the router level and then injecting your own Context:

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc