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

@pinia/colada

Package Overview
Dependencies
Maintainers
0
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pinia/colada - npm Package Compare versions

Comparing version 0.6.0 to 0.7.0

330

dist/index.d.ts
import * as vue from 'vue';
import { Ref, ComputedRef, ShallowRef, App, MaybeRefOrGetter } from 'vue';
import { Ref, ComputedRef, MaybeRefOrGetter, ShallowRef, App } from 'vue';
import * as pinia from 'pinia';
import { Pinia } from 'pinia';

@@ -82,2 +83,7 @@ type EntryNodeKey = string | number;

/**
* Key used to identify a query or a mutation. Always an array.
*/
type EntryKey = Array<EntryNodeKey | _ObjectFlat>;
/**
* Allows you to extend the default types of the library.

@@ -106,2 +112,103 @@ *

/**
* `true` refetch if data is stale (refresh()), `false` never refetch, 'always' always refetch.
*/
type _RefetchOnControl = boolean | 'always';
/**
* Context object passed to the `query` function of `useQuery()`.
* @see {@link UseQueryOptions}
*/
interface UseQueryFnContext {
/**
* `AbortSignal` instance attached to the query call. If the call becomes outdated (e.g. due to a new call with the
* same key), the signal will be aborted.
*/
signal: AbortSignal;
}
/**
* Options for `useQuery()`. Can be extended by plugins.
*
* @example
* ```ts
* // use-query-plugin.d.ts
* export {} // needed
* declare module '@pinia/colada' {
* interface UseQueryOptions {
* // Whether to refresh the data when the component is mounted.
* refreshOnMount?: boolean
* }
* }
* ```
*/
interface UseQueryOptions<TResult = unknown, TError = ErrorDefault> {
/**
* The key used to identify the query. Array of primitives **without** reactive values or a reactive array or getter.
* It should be treaded as an array of dependencies of your queries, e.g. if you use the `route.params.id` property,
* it should also be part of the key:
*
* ```ts
* import { useRoute } from 'vue-router'
* import { useQuery } from '@pinia/colada'
*
* const route = useRoute()
* const { data } = useQuery({
* // pass a getter function (or computed, ref, etc.) to ensure reactivity
* key: () => ['user', route.params.id],
* query: () => fetchUser(route.params.id),
* })
* ```
*/
key: MaybeRefOrGetter<EntryKey>;
/**
* The function that will be called to fetch the data. It **must** be async.
*/
query: (context: UseQueryFnContext) => Promise<TResult>;
/**
* Whether the query should be enabled or not. If `false`, the query will not be executed until `refetch()` or
* `refresh()` is called. If it becomes `true`, the query will be refreshed.
*/
enabled?: MaybeRefOrGetter<boolean>;
/**
* Time in ms after which the data is considered stale and will be refreshed on next read
*/
staleTime?: number;
/**
* Time in ms after which, once the data is no longer being used, it will be garbage collected to free resources. TODO: **NOT IMPLEMENTED YET**
*/
gcTime?: number;
initialData?: () => TResult;
/**
* Function to type and ensure the `error` property is always an instance of `TError`.
*
* @param error - error thrown
* @example
* ```ts
* useQuery({
* key: ['user', id],
* query: () => fetchUser(id),
* transformError: (error): MyCustomError | UnexpectedError =>
* // this assumes both `MyCustomError` and a `UnexpectedError` are valid error classes
* error instanceof MyCustomError ? error : new UnexpectedError(error),
* })
* ```
*/
transformError?: (error: unknown) => TError;
refetchOnMount?: _RefetchOnControl;
refetchOnWindowFocus?: _RefetchOnControl;
refetchOnReconnect?: _RefetchOnControl;
}
/**
* Default options for `useQuery()`. Modifying this object will affect all the queries that don't override these
*/
declare const USE_QUERY_DEFAULTS: {
staleTime: number;
gcTime: number;
refetchOnWindowFocus: _RefetchOnControl;
refetchOnReconnect: _RefetchOnControl;
refetchOnMount: _RefetchOnControl;
enabled: MaybeRefOrGetter<boolean>;
transformError: (error: unknown) => any;
};
type UseQueryOptionsWithDefaults<TResult = unknown, TError = ErrorDefault> = UseQueryOptions<TResult, TError> & typeof USE_QUERY_DEFAULTS;
/**
* The status of the request.

@@ -146,2 +253,14 @@ * - `pending`: initial state

when: number;
/**
* The key associated with this query entry.
*/
key: EntryNodeKey[];
/**
* Components and effects scopes that use this query entry.
*/
deps: Set<unknown>;
/**
* Timeout id that scheduled a garbage collection. It is set here to clear it when the entry is used by a different component
*/
gcTimeout: ReturnType<typeof setTimeout> | undefined;
pending: null | {

@@ -155,41 +274,48 @@ abortController: AbortController;

*/
options?: UseQueryOptionsWithDefaults<TResult, TError>;
options: UseQueryOptionsWithDefaults<TResult, TError> | null;
/**
* Whether the data is stale or not, requires `options.staleTime` to be set.
*/
readonly stale: boolean;
}
declare const useQueryCache: pinia.StoreDefinition<"_pc_query", pinia._UnwrapAll<Pick<{
caches: vue.ShallowReactive<TreeMapNode<UseQueryEntry<unknown, unknown>>>;
ensureEntry: <TResult = unknown, TError = Error>(keyRaw: UseQueryKey, options: UseQueryOptionsWithDefaults<TResult, TError>) => UseQueryEntry<TResult, TError>;
ensureDefinedQuery: <T>(fn: () => T) => T;
invalidateEntry: (key: UseQueryKey, { refetch: shouldRefetch, exact, }?: {
refetch?: boolean | undefined;
exact?: boolean | undefined;
ensureEntry: <TResult = unknown, TError = Error>(keyRaw: EntryKey, options: UseQueryOptionsWithDefaults<TResult, TError>) => UseQueryEntry<TResult, TError>;
ensureDefinedQuery: <T>(fn: () => T) => [entries: UseQueryEntry<unknown, unknown>[], returnValue: unknown];
invalidateEntry: (key: EntryKey, { refetch: shouldRefetch, exact, }?: {
refetch?: boolean;
exact?: boolean;
}) => Promise<unknown> | undefined;
setQueryData: <TResult_1 = unknown>(key: UseQueryKey, data: TResult_1 | ((data: Ref<TResult_1 | undefined>) => void)) => void;
getQueryData: <TResult_2 = unknown>(key: UseQueryKey) => TResult_2 | undefined;
refetch: <TResult_3, TError_1>(entry: UseQueryEntry<TResult_3, TError_1>) => Promise<TResult_3>;
refresh: <TResult_4, TError_2>(entry: UseQueryEntry<TResult_4, TError_2>) => Promise<TResult_4>;
setQueryData: <TResult = unknown>(key: EntryKey, data: TResult | ((data: Ref<TResult | undefined>) => void)) => void;
getQueryData: <TResult = unknown>(key: EntryKey) => TResult | undefined;
deleteQueryData: (key: EntryKey) => void;
refetch: <TResult, TError>(entry: UseQueryEntry<TResult, TError>) => Promise<TResult>;
refresh: <TResult, TError>(entry: UseQueryEntry<TResult, TError>) => Promise<TResult>;
}, "caches">>, Pick<{
caches: vue.ShallowReactive<TreeMapNode<UseQueryEntry<unknown, unknown>>>;
ensureEntry: <TResult = unknown, TError = Error>(keyRaw: UseQueryKey, options: UseQueryOptionsWithDefaults<TResult, TError>) => UseQueryEntry<TResult, TError>;
ensureDefinedQuery: <T>(fn: () => T) => T;
invalidateEntry: (key: UseQueryKey, { refetch: shouldRefetch, exact, }?: {
refetch?: boolean | undefined;
exact?: boolean | undefined;
ensureEntry: <TResult = unknown, TError = Error>(keyRaw: EntryKey, options: UseQueryOptionsWithDefaults<TResult, TError>) => UseQueryEntry<TResult, TError>;
ensureDefinedQuery: <T>(fn: () => T) => [entries: UseQueryEntry<unknown, unknown>[], returnValue: unknown];
invalidateEntry: (key: EntryKey, { refetch: shouldRefetch, exact, }?: {
refetch?: boolean;
exact?: boolean;
}) => Promise<unknown> | undefined;
setQueryData: <TResult_1 = unknown>(key: UseQueryKey, data: TResult_1 | ((data: Ref<TResult_1 | undefined>) => void)) => void;
getQueryData: <TResult_2 = unknown>(key: UseQueryKey) => TResult_2 | undefined;
refetch: <TResult_3, TError_1>(entry: UseQueryEntry<TResult_3, TError_1>) => Promise<TResult_3>;
refresh: <TResult_4, TError_2>(entry: UseQueryEntry<TResult_4, TError_2>) => Promise<TResult_4>;
setQueryData: <TResult = unknown>(key: EntryKey, data: TResult | ((data: Ref<TResult | undefined>) => void)) => void;
getQueryData: <TResult = unknown>(key: EntryKey) => TResult | undefined;
deleteQueryData: (key: EntryKey) => void;
refetch: <TResult, TError>(entry: UseQueryEntry<TResult, TError>) => Promise<TResult>;
refresh: <TResult, TError>(entry: UseQueryEntry<TResult, TError>) => Promise<TResult>;
}, never>, Pick<{
caches: vue.ShallowReactive<TreeMapNode<UseQueryEntry<unknown, unknown>>>;
ensureEntry: <TResult = unknown, TError = Error>(keyRaw: UseQueryKey, options: UseQueryOptionsWithDefaults<TResult, TError>) => UseQueryEntry<TResult, TError>;
ensureDefinedQuery: <T>(fn: () => T) => T;
invalidateEntry: (key: UseQueryKey, { refetch: shouldRefetch, exact, }?: {
refetch?: boolean | undefined;
exact?: boolean | undefined;
ensureEntry: <TResult = unknown, TError = Error>(keyRaw: EntryKey, options: UseQueryOptionsWithDefaults<TResult, TError>) => UseQueryEntry<TResult, TError>;
ensureDefinedQuery: <T>(fn: () => T) => [entries: UseQueryEntry<unknown, unknown>[], returnValue: unknown];
invalidateEntry: (key: EntryKey, { refetch: shouldRefetch, exact, }?: {
refetch?: boolean;
exact?: boolean;
}) => Promise<unknown> | undefined;
setQueryData: <TResult_1 = unknown>(key: UseQueryKey, data: TResult_1 | ((data: Ref<TResult_1 | undefined>) => void)) => void;
getQueryData: <TResult_2 = unknown>(key: UseQueryKey) => TResult_2 | undefined;
refetch: <TResult_3, TError_1>(entry: UseQueryEntry<TResult_3, TError_1>) => Promise<TResult_3>;
refresh: <TResult_4, TError_2>(entry: UseQueryEntry<TResult_4, TError_2>) => Promise<TResult_4>;
}, "ensureEntry" | "ensureDefinedQuery" | "invalidateEntry" | "setQueryData" | "getQueryData" | "refetch" | "refresh">>;
setQueryData: <TResult = unknown>(key: EntryKey, data: TResult | ((data: Ref<TResult | undefined>) => void)) => void;
getQueryData: <TResult = unknown>(key: EntryKey) => TResult | undefined;
deleteQueryData: (key: EntryKey) => void;
refetch: <TResult, TError>(entry: UseQueryEntry<TResult, TError>) => Promise<TResult>;
refresh: <TResult, TError>(entry: UseQueryEntry<TResult, TError>) => Promise<TResult>;
}, "refetch" | "ensureEntry" | "ensureDefinedQuery" | "invalidateEntry" | "setQueryData" | "getQueryData" | "deleteQueryData" | "refresh">>;
/**

@@ -287,104 +413,37 @@ * Raw data of a query entry. Can be serialized from the server and used to hydrate the store.

transformError?: (error: unknown) => ErrorDefault;
}
declare function QueryPlugin(app: App, { onSuccess, onSettled, onError, ...useQueryOptions }?: QueryPluginOptions): void;
/**
* `true` refetch if data is stale (refresh()), `false` never refetch, 'always' always refetch.
*/
type _RefetchOnControl = boolean | 'always';
/**
* Key used to identify a query. Always an array.
*/
type UseQueryKey = Array<EntryNodeKey | _ObjectFlat>;
/**
* Context object passed to the `query` function of `useQuery()`.
* @see {@link UseQueryOptions}
*/
interface UseQueryFnContext {
/**
* `AbortSignal` instance attached to the query call. If the call becomes outdated (e.g. due to a new call with the
* same key), the signal will be aborted.
* Pinia instance to use. This is only needed if installing before the Pinia plugin.
*/
signal: AbortSignal;
pinia?: Pinia;
}
/**
* Options for `useQuery()`. Can be extended by plugins.
* Plugin for the Pinia Colada Query functionality.
* @param app - Vue App
* @param options
*
* @example
* ```ts
* // use-query-plugin.d.ts
* export {} // needed
* declare module '@pinia/colada' {
* interface UseQueryOptions {
* // Whether to refresh the data when the component is mounted.
* refreshOnMount?: boolean
* }
* }
* ```
* @deprecated Use `PiniaColada` instead
*/
interface UseQueryOptions<TResult = unknown, TError = ErrorDefault> {
declare function QueryPlugin(app: App, { onSuccess, onSettled, onError, pinia, ...useQueryOptions }?: QueryPluginOptions): void;
/**
* Context passed to a Pinia Colada plugin.
*/
interface PiniaColadaPluginContext {
/**
* The key used to identify the query. Array of primitives **without** reactive values or a reactive array or getter.
* It should be treaded as an array of dependencies of your queries, e.g. if you use the `route.params.id` property,
* it should also be part of the key:
*
* ```ts
* import { useRoute } from 'vue-router'
* import { useQuery } from '@pinia/colada'
*
* const route = useRoute()
* const { data } = useQuery({
* // pass a getter function (or computed, ref, etc.) to ensure reactivity
* key: () => ['user', route.params.id],
* query: () => fetchUser(route.params.id),
* })
* ```
* The query cache used by the application.
*/
key: MaybeRefOrGetter<UseQueryKey>;
cache: ReturnType<typeof useQueryCache>;
/**
* The function that will be called to fetch the data. It **must** be async.
* The Pinia instance used by the application.
*/
query: (context: UseQueryFnContext) => Promise<TResult>;
/**
* Time in ms after which the data is considered stale and will be refreshed on next read
*/
staleTime?: number;
/**
* Time in ms after which, once the data is no longer being used, it will be garbage collected to free resources. TODO: **NOT IMPLEMENTED YET**
*/
gcTime?: number;
initialData?: () => TResult;
/**
* Function to type and ensure the `error` property is always an instance of `TError`.
*
* @param error - error thrown
* @example
* ```ts
* useQuery({
* key: ['user', id],
* query: () => fetchUser(id),
* transformError: (error): MyCustomError | UnexpectedError =>
* // this assumes both `MyCustomError` and a `UnexpectedError` are valid error classes
* error instanceof MyCustomError ? error : new UnexpectedError(error),
* })
* ```
*/
transformError?: (error: unknown) => TError;
refetchOnMount?: _RefetchOnControl;
refetchOnWindowFocus?: _RefetchOnControl;
refetchOnReconnect?: _RefetchOnControl;
pinia: Pinia;
}
/**
* Default options for `useQuery()`. Modifying this object will affect all the queries that don't override these
* A Pinia Colada plugin.
*/
declare const USE_QUERY_DEFAULTS: {
staleTime: number;
gcTime: number;
refetchOnWindowFocus: _RefetchOnControl;
refetchOnReconnect: _RefetchOnControl;
refetchOnMount: _RefetchOnControl;
transformError: (error: unknown) => any;
};
type UseQueryOptionsWithDefaults<TResult = unknown, TError = ErrorDefault> = typeof USE_QUERY_DEFAULTS & UseQueryOptions<TResult, TError>;
interface PiniaColadaPlugin {
(context: PiniaColadaPluginContext): void;
}
type _MutationKey<TVars> = EntryKey | ((vars: TVars) => EntryKey);
/**

@@ -394,3 +453,3 @@ * The keys to invalidate when a mutation succeeds.

*/
type _MutationKeys<TVars, TResult> = UseQueryKey[] | ((data: TResult, vars: TVars) => UseQueryKey[]);
type _MutationKeys<TVars, TResult> = EntryKey[] | ((data: TResult, vars: TVars) => EntryKey[]);
/**

@@ -441,2 +500,3 @@ * The status of the mutation.

mutation: (vars: TVars, context: NoInfer<TContext>) => Promise<TResult>;
key?: _MutationKey<TVars>;
/**

@@ -600,3 +660,4 @@ * Keys to invalidate if the mutation succeeds so that `useQuery()` refetch if used.

* Define a query with a setup function. Allows to return arbitrary values from the query function, create contextual
* refs, rename the returned values, etc.
* refs, rename the returned values, etc. The setup function will be called only once, like stores, and **must be
* synchronous**.
*

@@ -620,2 +681,29 @@ * @param setup - a function to setup the query

export { type EntryNodeKey, type MutationStatus, QueryPlugin, type QueryPluginOptions, type QueryStatus, TreeMapNode, type TypesConfig, type UseMutationOptions, type UseMutationReturn, type UseQueryEntry, type UseQueryKey, type UseQueryOptions, type UseQueryOptionsWithDefaults, type UseQueryReturn, type _Awaitable, type _EmptyObject, type _MaybeArray, type _ReduceContext, defineMutation, defineQuery, delayLoadingRef, serialize, useMutation, useQuery, useQueryCache };
/**
* Options for the Pinia Colada plugin.
*/
interface PiniaColadaOptions extends QueryPluginOptions {
/**
* Pinia instance to use. This is only needed if installing before the Pinia plugin.
*/
pinia?: Pinia;
/**
* Pinia Colada plugins to install.
*/
plugins?: PiniaColadaPlugin[];
}
/**
* Plugin that installs the Query and Mutation plugins alongside some extra plugins.
*
* @see {@link QueryPlugin} to only install the Query plugin.
* @see {@link MutationPlugin} to only install the Query plugin.
*
* @param app - Vue App
* @param options - Pinia Colada options
* @param options.pinia - Pinia instance to use. This is only needed if installing before the Pinia plugin.
* @param options.query - Query plugin options
* @param options.plugins - Pinia Colada plugins to install.
*/
declare function PiniaColada(app: App, options?: PiniaColadaOptions): void;
export { type EntryKey, type EntryNodeKey, type MutationStatus, PiniaColada, type PiniaColadaOptions, type PiniaColadaPlugin, type PiniaColadaPluginContext, QueryPlugin, type QueryPluginOptions, type QueryStatus, TreeMapNode, type TypesConfig, type UseMutationOptions, type UseMutationReturn, type UseQueryEntry, type UseQueryOptions, type UseQueryOptionsWithDefaults, type UseQueryReturn, type _Awaitable, type _EmptyObject, type _MaybeArray, type _ReduceContext, defineMutation, defineQuery, delayLoadingRef, serialize, useMutation, useQuery, useQueryCache };

@@ -1,3 +0,18 @@

// src/use-mutation.ts
import { computed as computed3, shallowRef as shallowRef2 } from "vue";
// src/query-options.ts
import { inject } from "vue";
var USE_QUERY_DEFAULTS = {
staleTime: 1e3 * 5,
// 5 seconds
gcTime: 1e3 * 60 * 5,
// 5 minutes
// avoid type narrowing to `true`
refetchOnWindowFocus: true,
refetchOnReconnect: true,
refetchOnMount: true,
enabled: true,
// as any to simplify the typing with generics
transformError: (error) => error
};
var USE_QUERY_OPTIONS_KEY = process.env.NODE_ENV !== "production" ? Symbol("useQueryOptions") : Symbol();
var useQueryOptions = () => inject(USE_QUERY_OPTIONS_KEY);

@@ -11,3 +26,2 @@ // src/query-store.ts

shallowRef,
toValue as toValue2,
triggerRef

@@ -142,3 +156,17 @@ } from "vue";

// src/query-store.ts
function createQueryEntry(initialData, error = null, when = 0) {
function queryEntry_addDep(entry, effect) {
if (!effect) return;
entry.deps.add(effect);
clearTimeout(entry.gcTimeout);
}
function queryEntry_removeDep(entry, effect, store) {
if (!effect) return;
entry.deps.delete(effect);
if (entry.deps.size > 0 || !entry.options) return;
clearTimeout(entry.gcTimeout);
entry.gcTimeout = setTimeout(() => {
store.deleteQueryData(entry.key);
}, entry.options.gcTime);
}
function createQueryEntry(key, initialData, error = null, when = 0) {
const data = shallowRef(initialData);

@@ -149,2 +177,3 @@ const status = shallowRef(

return {
key,
data,

@@ -156,3 +185,9 @@ error: shallowRef(error),

isFetching: computed2(() => status.value === "loading"),
pending: null
pending: null,
deps: /* @__PURE__ */ new Set(),
gcTimeout: void 0,
options: null,
get stale() {
return Date.now() > this.when + this.options.staleTime;
}
};

@@ -166,14 +201,29 @@ }

var QUERY_STORE_ID = "_pc_query";
var useQueryCache = defineStore(QUERY_STORE_ID, () => {
var useQueryCache = defineStore(QUERY_STORE_ID, ({ action }) => {
const cachesRaw = new TreeMapNode();
const caches = shallowReactive(cachesRaw);
const scope = getCurrentScope2();
let currentDefineQueryEntry;
const defineQueryMap = /* @__PURE__ */ new WeakMap();
function ensureDefinedQuery(fn) {
if (!defineQueryMap.has(fn)) {
defineQueryMap.set(fn, scope.run(fn));
const ensureDefinedQuery = action((fn) => {
let defineQueryEntry = defineQueryMap.get(fn);
if (!defineQueryEntry) {
currentDefineQueryEntry = defineQueryEntry = [[], null];
defineQueryEntry[1] = scope.run(fn);
currentDefineQueryEntry = null;
defineQueryMap.set(fn, defineQueryEntry);
} else {
for (const queryEntry of defineQueryEntry[0]) {
if (queryEntry.options?.refetchOnMount) {
if (queryEntry.options.refetchOnMount === "always") {
refetch(queryEntry);
} else {
refresh(queryEntry);
}
}
}
}
return defineQueryMap.get(fn);
}
function ensureEntry(keyRaw, options) {
return defineQueryEntry;
});
const ensureEntry = action((keyRaw, options) => {
if (process.env.NODE_ENV !== "production" && keyRaw.length === 0) {

@@ -189,17 +239,17 @@ throw new Error(

key,
entry = scope.run(() => createQueryEntry(options.initialData?.()))
entry = scope.run(
() => createQueryEntry(key, options.initialData?.())
)
);
}
if (!entry.options) {
entry.options = options;
}
entry.options ??= options;
currentDefineQueryEntry?.[0].push(entry);
return entry;
}
function invalidateEntry(key, {
});
const invalidateEntry = action((key, {
refetch: shouldRefetch = true,
exact = false
} = {}) {
} = {}) => {
const entryNode = cachesRaw.find(key.map(stringifyFlatObject));
if (!entryNode)
return;
if (!entryNode) return;
const list = exact ? entryNode.value != null ? [entryNode.value] : [] : [...entryNode];

@@ -213,4 +263,4 @@ for (const entry of list) {

}
}
async function refresh(entry) {
});
const refresh = action(async (entry) => {
if (process.env.NODE_ENV !== "production" && !entry.options) {

@@ -221,10 +271,8 @@ throw new Error(

}
const { staleTime } = entry.options;
const _key = toValue2(entry.options.key).map(stringifyFlatObject);
if (entry.error.value || isExpired(entry.when, staleTime)) {
if (entry.error.value || entry.stale) {
await (entry.pending?.refreshCall ?? refetch(entry));
}
return entry.data.value;
}
async function refetch(entry) {
});
const refetch = action(async (entry) => {
if (process.env.NODE_ENV !== "production" && !entry.options) {

@@ -235,3 +283,2 @@ throw new Error(

}
const _key = toValue2(entry.options.key).map(stringifyFlatObject);
entry.status.value = "loading";

@@ -264,7 +311,6 @@ const abortController = new AbortController();

return entry.data.value;
}
function setQueryData(key, data) {
});
const setQueryData = action((key, data) => {
const entry = caches.get(key.map(stringifyFlatObject));
if (!entry)
return;
if (!entry) return;
if (typeof data === "function") {

@@ -278,9 +324,12 @@ ;

entry.error.value = null;
}
function getQueryData(key) {
});
const getQueryData = action((key) => {
const entry = caches.get(key.map(stringifyFlatObject));
return entry?.data.value;
}
function _preload(_useQueryFn) {
}
});
const deleteQueryData = action((key) => {
caches.delete(key.map(stringifyFlatObject));
});
const _preload = action((_useQueryFn) => {
});
return {

@@ -300,2 +349,3 @@ caches,

getQueryData,
deleteQueryData,
refetch,

@@ -305,5 +355,2 @@ refresh

});
function isExpired(lastRefresh, staleTime) {
return Date.now() > lastRefresh + staleTime;
}
function serialize(root) {

@@ -320,3 +367,36 @@ return root.children ? [...root.children.entries()].map(_serialize) : [];

// src/query-plugin.ts
function QueryPlugin(app, {
onSuccess = noop,
onSettled = noop,
onError = noop,
pinia = app.config.globalProperties.$pinia,
...useQueryOptions2
} = {}) {
app.provide(USE_QUERY_OPTIONS_KEY, {
...USE_QUERY_DEFAULTS,
...useQueryOptions2
});
if (process.env.NODE_ENV !== "production" && !pinia) {
throw new Error(
'[@pinia/colada] root pinia plugin not detected. Make sure you install pinia before installing the "QueryPlugin" plugin or to manually pass the pinia instance.'
);
}
const store = useQueryCache(pinia);
store.$onAction(({ name, after, onError: _onError }) => {
if (name === "refetch") {
after(async (data) => {
await onSuccess(data);
onSettled(data, null);
});
_onError(async (error) => {
await onError(error);
onSettled(void 0, error);
});
}
});
}
// src/use-mutation.ts
import { computed as computed3, shallowRef as shallowRef2 } from "vue";
function useMutation(options) {

@@ -399,28 +479,43 @@ const store = useQueryCache();

computed as computed4,
getCurrentInstance,
getCurrentScope as getCurrentScope3,
getCurrentInstance as getCurrentInstance2,
getCurrentScope as getCurrentScope4,
onMounted,
onScopeDispose as onScopeDispose2,
onScopeDispose as onScopeDispose3,
onServerPrefetch,
onUnmounted,
toValue as toValue3,
toValue as toValue2,
watch as watch2
} from "vue";
// src/query-options.ts
import { inject } from "vue";
var USE_QUERY_DEFAULTS = {
staleTime: 1e3 * 5,
// 5 seconds
gcTime: 1e3 * 60 * 5,
// 5 minutes
// avoid type narrowing to `true`
refetchOnWindowFocus: true,
refetchOnReconnect: true,
refetchOnMount: true,
// as any to simplify the typing with generics
transformError: (error) => error
};
var USE_QUERY_OPTIONS_KEY = process.env.NODE_ENV !== "production" ? Symbol("useQueryOptions") : Symbol();
var useQueryOptions = () => inject(USE_QUERY_OPTIONS_KEY);
// src/define-query.ts
import {
getCurrentInstance,
getCurrentScope as getCurrentScope3,
onScopeDispose as onScopeDispose2
} from "vue";
var currentDefineQueryEffect;
function getCurrentDefineQueryEffect() {
return currentDefineQueryEffect;
}
function defineQuery(optionsOrSetup) {
const setupFn = typeof optionsOrSetup === "function" ? optionsOrSetup : () => useQuery(optionsOrSetup);
return () => {
const store = useQueryCache();
const previousEffect = currentDefineQueryEffect;
const currentScope = getCurrentInstance() || (currentDefineQueryEffect = getCurrentScope3());
const [entries, ret] = store.ensureDefinedQuery(setupFn);
if (currentScope) {
entries.forEach((entry) => {
queryEntry_addDep(entry, currentScope);
});
onScopeDispose2(() => {
entries.forEach((entry) => {
queryEntry_removeDep(entry, currentScope, store);
});
});
}
currentDefineQueryEffect = previousEffect;
return ret;
};
}

@@ -436,3 +531,3 @@ // src/use-query.ts

const entry = computed4(
() => store.ensureEntry(toValue3(options.key), options)
() => store.ensureEntry(toValue2(options.key), options)
);

@@ -450,7 +545,7 @@ const refresh = () => store.refresh(entry.value);

};
const hasCurrentInstance = getCurrentInstance();
const hasCurrentInstance = getCurrentInstance2();
const currentEffect = getCurrentDefineQueryEffect() || getCurrentScope4();
if (hasCurrentInstance) {
onServerPrefetch(async () => {
await refresh();
queryReturn.data.value, queryReturn.error.value, queryReturn.isFetching.value, queryReturn.isPending.value;
if (toValue2(options.enabled)) await refresh();
});

@@ -462,16 +557,38 @@ }

isActive = true;
queryEntry_addDep(entry.value, hasCurrentInstance);
});
onUnmounted(() => {
queryEntry_removeDep(entry.value, hasCurrentInstance, store);
});
} else {
isActive = true;
if (currentEffect) {
queryEntry_addDep(entry.value, currentEffect);
onScopeDispose3(() => {
queryEntry_removeDep(entry.value, currentEffect, store);
});
}
}
watch2(entry, (entry2, _, onCleanup) => {
if (!isActive)
return;
refresh();
onCleanup(() => {
watch2(
entry,
(entry2, previousEntry) => {
if (!isActive) return;
if (previousEntry) {
queryEntry_removeDep(previousEntry, hasCurrentInstance, store);
queryEntry_removeDep(previousEntry, currentEffect, store);
}
queryEntry_addDep(entry2, hasCurrentInstance);
queryEntry_addDep(entry2, currentEffect);
if (toValue2(options.enabled)) refresh();
},
{ immediate: true }
);
if (typeof options.enabled !== "boolean") {
watch2(options.enabled, (newEnabled) => {
if (newEnabled) refresh();
});
});
if (options.refetchOnMount && hasCurrentInstance) {
}
if (hasCurrentInstance) {
onMounted(() => {
if (options.refetchOnMount) {
if ((options.refetchOnMount || queryReturn.status.value === "pending") && toValue2(options.enabled)) {
if (options.refetchOnMount === "always") {

@@ -485,10 +602,6 @@ refetch();

}
if (getCurrentScope3()) {
onScopeDispose2(() => {
});
}
if (IS_CLIENT) {
if (options.refetchOnWindowFocus) {
useEventListener(document, "visibilitychange", () => {
if (document.visibilityState === "visible") {
if (document.visibilityState === "visible" && toValue2(options.enabled)) {
if (options.refetchOnWindowFocus === "always") {

@@ -504,6 +617,8 @@ refetch();

useEventListener(window, "online", () => {
if (options.refetchOnReconnect === "always") {
refetch();
} else {
refresh();
if (toValue2(options.enabled)) {
if (options.refetchOnReconnect === "always") {
refetch();
} else {
refresh();
}
}

@@ -520,40 +635,10 @@ });

// src/define-query.ts
function defineQuery(optionsOrSetup) {
const setupFn = typeof optionsOrSetup === "function" ? optionsOrSetup : () => useQuery(optionsOrSetup);
return () => useQueryCache().ensureDefinedQuery(setupFn);
// src/index.ts
function PiniaColada(app, options = {}) {
app.use(QueryPlugin, options);
const { plugins, pinia = app.config.globalProperties.$pinia } = options;
plugins?.forEach((plugin) => plugin({ cache: useQueryCache(pinia), pinia }));
}
// src/query-plugin.ts
function QueryPlugin(app, {
onSuccess = noop,
onSettled = noop,
onError = noop,
...useQueryOptions2
} = {}) {
app.provide(USE_QUERY_OPTIONS_KEY, {
...USE_QUERY_DEFAULTS,
...useQueryOptions2
});
const pinia = app.config.globalProperties.$pinia;
if (process.env.NODE_ENV !== "production" && !pinia) {
throw new Error(
'[@pinia/colada] root pinia plugin not detected. Make sure you install pinia before installing the "QueryPlugin" plugin.'
);
}
const store = useQueryCache(pinia);
store.$onAction(({ name, after, onError: _onError }) => {
if (name === "refetch" || name === "refresh") {
after(async (data) => {
await onSuccess(data);
onSettled(data, null);
});
_onError(async (error) => {
await onError(error);
onSettled(void 0, error);
});
}
});
}
export {
PiniaColada,
QueryPlugin,

@@ -560,0 +645,0 @@ TreeMapNode,

{
"name": "@pinia/colada",
"type": "module",
"version": "0.6.0",
"packageManager": "pnpm@8.14.1",
"version": "0.7.0",
"description": "The smart data fetching layer for Pinia",

@@ -63,19 +62,2 @@ "publishConfig": {

],
"scripts": {
"dev": "vitest --ui --typecheck",
"docs": "vitepress dev docs",
"docs:build": "pnpm run docs:api:build && vitepress build docs",
"docs:api:build": "node ./scripts/run-typedoc.js",
"play": "pnpm -C playground dev",
"prepublishOnly": "pnpm run build",
"release": "standard-version",
"test": "pnpm run test:cov && pnpm run test:types",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"test:types": "tsc --build ./tsconfig.json",
"test:cov": "vitest run --typecheck --coverage",
"build": "tsup",
"size": "size-limit",
"prepare": "simple-git-hooks"
},
"size-limit": [

@@ -102,26 +84,26 @@ {

"devDependencies": {
"@antfu/eslint-config": "^2.8.3",
"@pinia/colada": "workspace:*",
"@shikijs/vitepress-twoslash": "^1.2.0",
"@size-limit/preset-small-lib": "^11.1.1",
"@types/node": "^20.11.30",
"@vitejs/plugin-vue": "^5.0.4",
"@vitest/coverage-v8": "^1.4.0",
"@vitest/ui": "^1.4.0",
"@vue/test-utils": "^2.4.5",
"eslint": "^8.57.0",
"happy-dom": "^14.2.0",
"lint-staged": "^15.2.2",
"pinia": "^2.1.7",
"prettier": "^3.2.5",
"simple-git-hooks": "^2.11.0",
"size-limit": "^11.1.1",
"@antfu/eslint-config": "^2.23.2",
"@shikijs/vitepress-twoslash": "^1.11.2",
"@size-limit/preset-small-lib": "^11.1.4",
"@types/node": "^20.14.12",
"@vitejs/plugin-vue": "^5.1.0",
"@vitest/coverage-v8": "^2.0.4",
"@vitest/ui": "^2.0.4",
"@vue/test-utils": "^2.4.6",
"eslint": "^9.7.0",
"happy-dom": "^14.12.3",
"lint-staged": "^15.2.7",
"pinia": "^2.2.0",
"prettier": "^3.3.3",
"simple-git-hooks": "^2.11.1",
"size-limit": "^11.1.4",
"standard-version": "^9.5.0",
"tsup": "^8.0.2",
"typedoc": "^0.25.12",
"typedoc-plugin-markdown": "^3.17.1",
"typescript": "~5.4.3",
"vitepress": "1.0.0-rc.45",
"vitest": "^1.4.0",
"vue": "^3.4.21"
"tsup": "^8.2.3",
"typedoc": "^0.26.5",
"typedoc-plugin-markdown": "^4.2.3",
"typescript": "~5.5.4",
"vitepress": "1.3.1",
"vitest": "^2.0.4",
"vue": "^3.4.34",
"@pinia/colada": "0.7.0"
},

@@ -136,3 +118,18 @@ "simple-git-hooks": {

]
},
"scripts": {
"dev": "vitest --ui",
"docs": "vitepress dev docs",
"docs:build": "pnpm run docs:api:build && vitepress build docs",
"docs:api:build": "node ./scripts/run-typedoc.js",
"play": "pnpm -C playground dev",
"release": "standard-version",
"test": "pnpm run test:cov && pnpm run test:types",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"test:types": "tsc --build ./tsconfig.json",
"test:cov": "vitest run --coverage",
"build": "tsup",
"size": "size-limit"
}
}
}

@@ -32,3 +32,3 @@ <p align="center">

Pinia Colada is an opinionated yet flexible data fetching layer on top of Pinia. It features
Pinia Colada is an opinionated yet flexible data fetching layer on top of Pinia. It's built as a set of **pinia plugins**, **stores** and **composables** to benefit from Pinia's features and ecosystem. Pinia Colada has:

@@ -35,0 +35,0 @@ - ⚡️ **Automatic caching**: Smart client-side caching with request deduplication

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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