diff --git a/src/data-loaders/createDataLoader.ts b/src/data-loaders/createDataLoader.ts index 4d00f43f8..3b5ada553 100644 --- a/src/data-loaders/createDataLoader.ts +++ b/src/data-loaders/createDataLoader.ts @@ -8,14 +8,11 @@ import { type _Awaitable } from '../utils' /** * Base type for a data loader entry. Each Data Loader has its own entry in the `loaderEntries` (accessible via `[LOADER_ENTRIES_KEY]`) map. */ -export interface DataLoaderEntryBase< - isLazy extends boolean = boolean, - Data = unknown, -> { +export interface DataLoaderEntryBase { /** * Data stored in the entry. */ - data: ShallowRef<_DataMaybeLazy> + data: ShallowRef /** * Error if there was an error. @@ -32,7 +29,7 @@ export interface DataLoaderEntryBase< */ isLoading: ShallowRef - options: DefineDataLoaderOptionsBase + options: DefineDataLoaderOptionsBase /** * Called by the navigation guard when the navigation is duplicated. Should be used to reset pendingTo and pendingLoad and any other property that should be reset. @@ -86,7 +83,7 @@ export interface CreateDataLoaderOptions< after: (data: Data, context: Context) => unknown } -export interface DefineDataLoaderOptionsBase { +export interface DefineDataLoaderOptionsBase { /** * Whether the data should be lazy loaded without blocking the client side navigation or not. When set to true, the loader will no longer block the navigation and the returned composable can be called even * without having the data ready. @@ -94,7 +91,7 @@ export interface DefineDataLoaderOptionsBase { * @defaultValue `false` */ lazy?: - | isLazy + | boolean | (( to: RouteLocationNormalizedLoaded, from?: RouteLocationNormalizedLoaded @@ -143,7 +140,6 @@ export const toLazyValue = ( * - `after-load`: the data is committed after all non-lazy loaders have finished loading. */ export type DefineDataLoaderCommit = 'immediate' | 'after-load' -// TODO: is after-load fine or is it better to have an after-navigation instead export interface DataLoaderContextBase { /** @@ -153,11 +149,11 @@ export interface DataLoaderContextBase { } export interface DefineDataLoader { - ( + ( fn: DefineLoaderFn, - options?: DefineDataLoaderOptionsBase + options?: DefineDataLoaderOptionsBase // TODO: or a generic that allows a more complex UseDataLoader - ): UseDataLoader + ): UseDataLoader } // TODO: should be in each data loader. Refactor the base type to accept the needed generics @@ -166,10 +162,7 @@ export interface DefineDataLoader { * Data Loader composable returned by `defineLoader()`. * @see {@link DefineDataLoader} */ -export interface UseDataLoader< - isLazy extends boolean = boolean, - Data = unknown, -> { +export interface UseDataLoader { [IS_USE_DATA_LOADER_KEY]: true /** @@ -198,24 +191,21 @@ export interface UseDataLoader< // `return new NavigationResult()` in the loader Exclude, // or use it as a composable - UseDataLoaderResult> + UseDataLoaderResult> > /** * Internals of the data loader. * @internal */ - _: UseDataLoaderInternals> + _: UseDataLoaderInternals> } /** * Internal properties of a data loader composable. Used by the internal implementation of `defineLoader()`. **Should * not be used in application code.** */ -export interface UseDataLoaderInternals< - isLazy extends boolean = boolean, - Data = unknown, -> { +export interface UseDataLoaderInternals { /** * Loads the data from the cache if possible, otherwise loads it from the loader and awaits it. * @@ -234,7 +224,7 @@ export interface UseDataLoaderInternals< /** * Resolved options for the loader. */ - options: DefineDataLoaderOptionsBase + options: DefineDataLoaderOptionsBase /** * Gets the entry associated with the router instance. Assumes the data loader has been loaded and that the entry @@ -242,28 +232,17 @@ export interface UseDataLoaderInternals< * * @param router - router instance */ - getEntry(router: Router): DataLoaderEntryBase + getEntry(router: Router): DataLoaderEntryBase } -/** - * Generates the type for a `Ref` of a data loader based on the value of `lazy`. - * @internal - */ -export type _DataMaybeLazy = - // no lazy provided, default value is false - boolean extends isLazy ? Data : true extends isLazy ? Data | undefined : Data - /** * Return value of a loader composable defined with `defineLoader()`. */ -export interface UseDataLoaderResult< - isLazy extends boolean = boolean, - Data = unknown, -> { +export interface UseDataLoaderResult { /** * Data returned by the loader. If the data loader is lazy, it will be undefined until the first load. */ - data: ShallowRef<_DataMaybeLazy> + data: ShallowRef /** * Whether there is an ongoing request. diff --git a/src/data-loaders/defineColadaLoader.ts b/src/data-loaders/defineColadaLoader.ts index 616dc99ff..8e28200c4 100644 --- a/src/data-loaders/defineColadaLoader.ts +++ b/src/data-loaders/defineColadaLoader.ts @@ -13,7 +13,6 @@ import type { DefineLoaderFn, UseDataLoader, UseDataLoaderResult, - _DataMaybeLazy, _DefineLoaderEntryMap, } from 'unplugin-vue-router/runtime' import { @@ -60,40 +59,32 @@ import { toLazyValue } from './createDataLoader' * @param loader - function that returns a promise with the data * @param options - options to configure the data loader */ -export function defineColadaLoader< - Name extends keyof RouteMap, - Data, - isLazy extends boolean, ->( +export function defineColadaLoader( name: Name, - options: DefineDataColadaLoaderOptions -): UseDataLoaderColada -export function defineColadaLoader( - options: DefineDataColadaLoaderOptions -): UseDataLoaderColada + options: DefineDataColadaLoaderOptions +): UseDataLoaderColada +export function defineColadaLoader( + options: DefineDataColadaLoaderOptions +): UseDataLoaderColada -export function defineColadaLoader( +export function defineColadaLoader( nameOrOptions: | keyof RouteMap - | DefineDataColadaLoaderOptions, - _options?: DefineDataColadaLoaderOptions -): UseDataLoaderColada { + | DefineDataColadaLoaderOptions, + _options?: DefineDataColadaLoaderOptions +): UseDataLoaderColada { // TODO: make it DEV only and remove the first argument in production mode // resolve option overrides _options = _options || - (nameOrOptions as DefineDataColadaLoaderOptions< - isLazy, - keyof RouteMap, - Data - >) + (nameOrOptions as DefineDataColadaLoaderOptions) const loader = _options.query const options = { ...DEFAULT_DEFINE_LOADER_OPTIONS, ..._options, commit: _options?.commit || 'after-load', - } as DefineDataColadaLoaderOptions + } as DefineDataColadaLoaderOptions let isInitial = true @@ -104,10 +95,8 @@ export function defineColadaLoader( parent?: DataLoaderEntryBase, reload?: boolean ): Promise { - const entries = router[ - LOADER_ENTRIES_KEY - ]! as unknown as _DefineLoaderEntryMap< - DataLoaderColadaEntry + const entries = router[LOADER_ENTRIES_KEY]! as _DefineLoaderEntryMap< + DataLoaderColadaEntry > const isSSR = router[IS_SSR_KEY] const key = serializeQueryKey(options.key, to) @@ -115,7 +104,7 @@ export function defineColadaLoader( const route = shallowRef(to) entries.set(loader, { // force the type to match - data: shallowRef<_DataMaybeLazy>(), + data: shallowRef(), isLoading: shallowRef(false), error: shallowRef(), to, @@ -308,7 +297,7 @@ export function defineColadaLoader( } function commit( - this: DataLoaderColadaEntry, + this: DataLoaderColadaEntry, to: RouteLocationNormalizedLoaded ) { const key = serializeQueryKey(options.key, to) @@ -358,7 +347,7 @@ export function defineColadaLoader( // @ts-expect-error: requires the internals and symbol that are added later const useDataLoader: // for ts - UseDataLoaderColada = () => { + UseDataLoaderColada = () => { // work with nested data loaders const currentEntry = getCurrentContext() const [parentEntry, _router, _route] = currentEntry @@ -368,10 +357,8 @@ export function defineColadaLoader( const entries = router[ LOADER_ENTRIES_KEY - ]! as unknown as _DefineLoaderEntryMap< - DataLoaderColadaEntry - > - let entry = entries.get(loader) + ]! as unknown as _DefineLoaderEntryMap> + let entry = entries.get(loader) as DataLoaderColadaEntry | undefined if ( // if the entry doesn't exist, create it with load and ensure it's loading @@ -388,7 +375,7 @@ export function defineColadaLoader( ) } - entry = entries.get(loader)! + entry = entries.get(loader)! as DataLoaderColadaEntry // add ourselves to the parent entry children if (parentEntry) { @@ -450,7 +437,7 @@ export function defineColadaLoader( asyncStatus: ext!.asyncStatus, state: ext!.state, isPending: ext!.isPending, - } satisfies UseDataLoaderColadaResult + } satisfies UseDataLoaderColadaResult // load ensures there is a pending load const promise = entry @@ -489,11 +476,10 @@ export function defineColadaLoader( export const joinKeys = (keys: string[]): string => keys.join('|') export interface DefineDataColadaLoaderOptions< - isLazy extends boolean, Name extends keyof RouteMap, Data, -> extends DefineDataLoaderOptionsBase, - Omit, 'query' | 'key'> { +> extends DefineDataLoaderOptionsBase, + Omit, 'query' | 'key'> { /** * Key associated with the data and passed to pinia colada * @param to - Route to load the data @@ -517,8 +503,8 @@ export interface DefineDataColadaLoaderOptions< */ export interface DataColadaLoaderContext extends DataLoaderContextBase {} -export interface UseDataLoaderColadaResult - extends UseDataLoaderResult, +export interface UseDataLoaderColadaResult + extends UseDataLoaderResult, Pick< UseQueryReturn, 'isPending' | 'refetch' | 'refresh' | 'status' | 'asyncStatus' | 'state' @@ -527,8 +513,7 @@ export interface UseDataLoaderColadaResult /** * Data Loader composable returned by `defineColadaLoader()`. */ -export interface UseDataLoaderColada - extends UseDataLoader { +export interface UseDataLoaderColada extends UseDataLoader { /** * Data Loader composable returned by `defineColadaLoader()`. * @@ -555,12 +540,11 @@ export interface UseDataLoaderColada // `return new NavigationResult()` in the loader Exclude, // or use it as a composable - UseDataLoaderColadaResult> + UseDataLoaderColadaResult> > } -export interface DataLoaderColadaEntry - extends DataLoaderEntryBase { +export interface DataLoaderColadaEntry extends DataLoaderEntryBase { /** * Reactive route passed to pinia colada so it automatically refetch */ @@ -601,7 +585,7 @@ const DEFAULT_DEFINE_LOADER_OPTIONS = { server: true, commit: 'after-load', } satisfies Omit< - DefineDataColadaLoaderOptions, + DefineDataColadaLoaderOptions, 'key' | 'query' > @@ -622,7 +606,7 @@ const toValueWithParameters = ( * @param to - route to use */ function serializeQueryKey( - keyOption: DefineDataColadaLoaderOptions['key'], + keyOption: DefineDataColadaLoaderOptions['key'], to: RouteLocationNormalizedLoaded ): string[] { const key = toValueWithParameters(keyOption, to) diff --git a/src/data-loaders/defineLoader.spec.ts b/src/data-loaders/defineLoader.spec.ts index 4999a10de..c632ca19a 100644 --- a/src/data-loaders/defineLoader.spec.ts +++ b/src/data-loaders/defineLoader.spec.ts @@ -33,7 +33,7 @@ import { RouteLocationNormalizedLoaded } from 'vue-router' function mockedLoader( // boolean is easier to handle for router mock - options?: DefineDataLoaderOptions + options?: DefineDataLoaderOptions ) { const [spy, resolve, reject] = mockPromise( // not correct as T could be something else diff --git a/src/data-loaders/defineLoader.ts b/src/data-loaders/defineLoader.ts index 0e9ed546d..6571de4e3 100644 --- a/src/data-loaders/defineLoader.ts +++ b/src/data-loaders/defineLoader.ts @@ -12,7 +12,6 @@ import type { DefineLoaderFn, UseDataLoader, UseDataLoaderResult, - _DataMaybeLazy, } from 'unplugin-vue-router/runtime' import { ABORT_CONTROLLER_KEY, @@ -42,35 +41,31 @@ import { toLazyValue } from './createDataLoader' * @param loader - function that returns a promise with the data * @param options - options to configure the data loader */ -export function defineBasicLoader< - Name extends keyof RouteMap, - Data, - isLazy extends boolean, ->( +export function defineBasicLoader( name: Name, loader: DefineLoaderFn< Data, DataLoaderContext, RouteLocationNormalizedLoaded >, - options?: DefineDataLoaderOptions -): UseDataLoaderBasic -export function defineBasicLoader( + options?: DefineDataLoaderOptions +): UseDataLoaderBasic +export function defineBasicLoader( loader: DefineLoaderFn< Data, DataLoaderContext, RouteLocationNormalizedLoaded >, - options?: DefineDataLoaderOptions -): UseDataLoaderBasic + options?: DefineDataLoaderOptions +): UseDataLoaderBasic -export function defineBasicLoader( +export function defineBasicLoader( nameOrLoader: keyof RouteMap | DefineLoaderFn, _loaderOrOptions?: - | DefineDataLoaderOptions + | DefineDataLoaderOptions | DefineLoaderFn, - opts?: DefineDataLoaderOptions -): UseDataLoaderBasic { + opts?: DefineDataLoaderOptions +): UseDataLoaderBasic { // TODO: make it DEV only and remove the first argument in production mode // resolve option overrides const loader = @@ -78,13 +73,13 @@ export function defineBasicLoader( ? nameOrLoader : (_loaderOrOptions! as DefineLoaderFn) opts = typeof _loaderOrOptions === 'object' ? _loaderOrOptions : opts - // {} as DefineDataLoaderOptions, + const options = { ...DEFAULT_DEFINE_LOADER_OPTIONS, ...opts, // avoid opts overriding with `undefined` commit: opts?.commit || DEFAULT_DEFINE_LOADER_OPTIONS.commit, - } as DefineDataLoaderOptions + } as DefineDataLoaderOptions function load( to: RouteLocationNormalizedLoaded, @@ -99,7 +94,7 @@ export function defineBasicLoader( if (!entries.has(loader)) { entries.set(loader, { // force the type to match - data: shallowRef<_DataMaybeLazy>(), + data: shallowRef(), isLoading: shallowRef(false), error: shallowRef(), to, @@ -277,9 +272,9 @@ export function defineBasicLoader( } } - // @ts-expect-error: requires the internals and symbol that are added later - const useDataLoader: // for ts - UseDataLoaderBasic = () => { + // @ts-expect-error: return type has the generics + const useDataLoader // for ts + : UseDataLoaderBasic = () => { // work with nested data loaders const currentContext = getCurrentContext() const [parentEntry, _router, _route] = currentContext @@ -352,7 +347,7 @@ export function defineBasicLoader( }) // we only want the error if we are nesting the loader // otherwise this will end up in "Unhandled promise rejection" - .catch((e) => (parentEntry ? Promise.reject(e) : null)) + .catch((e: unknown) => (parentEntry ? Promise.reject(e) : null)) setCurrentContext(currentContext) return Object.assign(promise, useDataLoaderResult) @@ -374,8 +369,7 @@ export function defineBasicLoader( return useDataLoader } -export interface DefineDataLoaderOptions - extends DefineDataLoaderOptionsBase { +export interface DefineDataLoaderOptions extends DefineDataLoaderOptionsBase { /** * Key to use for SSR state. This will be used to read the initial data from `initialData`'s object. */ @@ -388,7 +382,7 @@ const DEFAULT_DEFINE_LOADER_OPTIONS = { lazy: false as boolean, server: true, commit: 'after-load', -} satisfies DefineDataLoaderOptions +} satisfies DefineDataLoaderOptions /** * Symbol used to store the data in the router so it can be retrieved after the initial navigation. @@ -415,5 +409,4 @@ declare module 'vue-router' { } } -export interface UseDataLoaderBasic - extends UseDataLoader {} +export interface UseDataLoaderBasic extends UseDataLoader {} diff --git a/src/data-loaders/index.ts b/src/data-loaders/index.ts index 5bbe06e32..3100635bf 100644 --- a/src/data-loaders/index.ts +++ b/src/data-loaders/index.ts @@ -6,7 +6,6 @@ export type { DataLoaderEntryBase, DefineDataLoaderOptionsBase, DefineLoaderFn, - _DataMaybeLazy, } from './createDataLoader' // new data fetching diff --git a/src/data-loaders/meta-extensions.ts b/src/data-loaders/meta-extensions.ts index 9d61a70be..5529127cc 100644 --- a/src/data-loaders/meta-extensions.ts +++ b/src/data-loaders/meta-extensions.ts @@ -16,10 +16,8 @@ import { type NavigationResult } from './navigation-guard' * @internal */ export type _DefineLoaderEntryMap< - DataLoaderEntry extends DataLoaderEntryBase< - boolean, - unknown - > = DataLoaderEntryBase, + DataLoaderEntry extends + DataLoaderEntryBase = DataLoaderEntryBase, > = WeakMap< // Depending on the `defineLoader()` they might use a different thing as key // e.g. an function for basic defineLoader, a doc instance for VueFire diff --git a/src/data-loaders/navigation-guard.spec.ts b/src/data-loaders/navigation-guard.spec.ts index ae4da4b47..eb4f1c682 100644 --- a/src/data-loaders/navigation-guard.spec.ts +++ b/src/data-loaders/navigation-guard.spec.ts @@ -30,7 +30,7 @@ import type { NavigationFailure } from 'vue-router' function mockedLoader( // boolean is easier to handle for router mock - options?: DefineDataLoaderOptions + options?: DefineDataLoaderOptions ) { const [spy, resolve, reject] = mockPromise( // not correct as T could be something else diff --git a/tests/data-loaders/tester.ts b/tests/data-loaders/tester.ts index af844693e..0ac7f1381 100644 --- a/tests/data-loaders/tester.ts +++ b/tests/data-loaders/tester.ts @@ -29,7 +29,7 @@ export function testDefineLoader( to: RouteLocationNormalizedLoaded, context: DataLoaderContextBase ) => Promise - } & DefineDataLoaderOptionsBase & { key?: string } + } & DefineDataLoaderOptionsBase & { key?: string } ) => UseDataLoader, { plugins, @@ -45,7 +45,7 @@ export function testDefineLoader( function mockedLoader( // boolean is easier to handle for router mock - options?: DefineDataLoaderOptionsBase & { key?: string } + options?: DefineDataLoaderOptionsBase & { key?: string } ) { const [spy, resolve, reject] = mockPromise( // not correct as T could be something else