first commit

This commit is contained in:
2026-05-12 12:41:49 +07:00
commit 604fef891f
8368 changed files with 1285228 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019-present Eduardo San Martin Morote
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+94
View File
@@ -0,0 +1,94 @@
# vue-router [![nmp version](https://img.shields.io/npm/v/vue-router.svg)](https://npmx.dev/package/vue-router) [![test](https://github.com/vuejs/router/actions/workflows/test.yml/badge.svg)](https://github.com/vuejs/router/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/vuejs/router/graph/badge.svg?token=azNM3FI0d1)](https://codecov.io/gh/vuejs/router)
> - This is the repository for Vue Router 4 (for Vue 3)
> - For Vue Router 3 (for Vue 2) see [vuejs/vue-router](https://github.com/vuejs/vue-router).
> To see what versions are currently supported, please refer to the [Security Policy](./packages/router/SECURITY.md).
<h2 align="center">Supporting Vue Router</h2>
Vue Router is part of the Vue Ecosystem and is an MIT-licensed open source project with its ongoing development made possible entirely by the support of Sponsors. If you would like to become a sponsor, please consider:
- [Become a Sponsor on GitHub](https://github.com/sponsors/posva)
- [One-time donation via PayPal](https://paypal.me/posva)
<!--sponsors start-->
<h4 align="center">Gold Sponsors</h4>
<p align="center">
<a href="https://www.coderabbit.ai/?utm_source=vuerouter&utm_medium=sponsor" target="_blank" rel="noopener noreferrer">
<picture>
<source srcset="https://posva-sponsors.pages.dev/logos/coderabbitai-dark.svg" media="(prefers-color-scheme: dark)" height="72px" alt="CodeRabbit" />
<img src="https://posva-sponsors.pages.dev/logos/coderabbitai-light.svg" height="72px" alt="CodeRabbit" />
</picture>
</a>
</p>
<h4 align="center">Silver Sponsors</h4>
<p align="center">
<a href="https://www.vuemastery.com/" target="_blank" rel="noopener noreferrer">
<picture>
<source srcset="https://posva-sponsors.pages.dev/logos/vuemastery-dark.png" media="(prefers-color-scheme: dark)" height="42px" alt="VueMastery" />
<img src="https://posva-sponsors.pages.dev/logos/vuemastery-light.svg" height="42px" alt="VueMastery" />
</picture>
</a>
<a href="https://www.controla.ai/?utm_source=posva" target="_blank" rel="noopener noreferrer">
<picture>
<source srcset="https://posva-sponsors.pages.dev/logos/controla-dark.png" media="(prefers-color-scheme: dark)" height="42px" alt="Controla" />
<img src="https://posva-sponsors.pages.dev/logos/controla-light.png" height="42px" alt="Controla" />
</picture>
</a>
<a href="https://jobs.sendcloud.com" target="_blank" rel="noopener noreferrer">
<picture>
<source srcset="https://posva-sponsors.pages.dev/logos/sendcloud-dark.svg" media="(prefers-color-scheme: dark)" height="42px" alt="SendCloud" />
<img src="https://posva-sponsors.pages.dev/logos/sendcloud-light.svg" height="42px" alt="SendCloud" />
</picture>
</a>
</p>
<h4 align="center">Bronze Sponsors</h4>
<p align="center">
<a href="https://www.rtvision.com/" target="_blank" rel="noopener noreferrer">
<picture>
<source srcset="https://avatars.githubusercontent.com/u/8292810" media="(prefers-color-scheme: dark)" height="26px" alt="RTVision" />
<img src="https://avatars.githubusercontent.com/u/8292810" height="26px" alt="RTVision" />
</picture>
</a>
<a href="https://storyblok.com" target="_blank" rel="noopener noreferrer">
<picture>
<source srcset="https://posva-sponsors.pages.dev/logos/storyblok.png" media="(prefers-color-scheme: dark)" height="26px" alt="Storyblok" />
<img src="https://posva-sponsors.pages.dev/logos/storyblok.png" height="26px" alt="Storyblok" />
</picture>
</a>
</p>
<!--sponsors end-->
---
Get started with the [documentation](https://router.vuejs.org).
## Quickstart
- Via CDN: `<script src="https://unpkg.com/vue-router@4"></script>`
- In-browser playground on [CodeSandbox](https://codesandbox.io/s/vue-router-4-reproduction-hb9lh)
- Add it to an existing Vue Project:
```bash
npm install vue-router@4
```
## Changes from Vue Router 3
Please consult the [Migration Guide](https://router.vuejs.org/guide/migration/).
## Contributing
See [Contributing Guide](https://github.com/vuejs/router/blob/main/.github/contributing.md).
## Special Thanks
<a href="https://www.browserstack.com">
<img src="https://github.com/vuejs/vue-router/raw/dev/assets/browserstack-logo-600x315.png" height="80" title="BrowserStack Logo" alt="BrowserStack Logo" />
</a>
Special thanks to [BrowserStack](https://www.browserstack.com) for letting the maintainers use their service to debug browser specific issues.
+1060
View File
File diff suppressed because it is too large Load Diff
+190
View File
@@ -0,0 +1,190 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { a as DefineLoaderFn, b as trackRoute, c as UseDataLoaderResult, d as DataLoaderPlugin, f as DataLoaderPluginOptions, g as useIsDataLoading, h as reroute, i as DefineDataLoaderOptionsBase_LaxData, l as toLazyValue, m as SetupLoaderGuardOptions, n as DataLoaderEntryBase, o as UseDataLoader, p as NavigationResult$1, r as DefineDataLoaderOptionsBase_DefinedData, s as UseDataLoaderInternals, t as DataLoaderContextBase, u as ErrorDefault, v as getCurrentContext, x as withLoaderContext, y as setCurrentContext } from "../index-ZwgQvn2r.js";
import { $ as MatcherPatternPathStatic, A as EXPERIMENTAL_RouterOptions, B as defineQueryParamParser, C as EXPERIMENTAL_RouteRecordNormalized_Group, Cn as RouteRecordRaw, D as EXPERIMENTAL_RouteRecord_Group, E as EXPERIMENTAL_RouteRecord_Base, F as createFixedResolver, H as normalizeParamParser, I as MatcherPatternQuery, J as MatcherPattern, K as EmptyParams, L as MatcherPatternQueryParam, M as EXPERIMENTAL_Router_Base, N as experimental_createRouter, Nt as RouteLocationNormalizedLoaded, O as EXPERIMENTAL_RouteRecord_Matchable, P as normalizeRouteRecord, Q as MatcherPatternPathDynamic_ParamOptions, R as defineParamParser, S as EXPERIMENTAL_RouteRecordNormalized, T as EXPERIMENTAL_RouteRecordRaw, U as PARAM_PARSER_INT, Un as TypesConfig, V as ExtractParamParserType, W as PARAM_PARSER_BOOL, X as MatcherPatternPath, Y as MatcherPatternHash, Z as MatcherPatternPathDynamic, et as MatcherQueryParams, j as EXPERIMENTAL_RouterOptions_Base, k as EXPERIMENTAL_Router, nt as ParamParser, q as MatcherParamsFormatted, rn as RouteMap, tt as MatcherQueryParamsValue, w as EXPERIMENTAL_RouteRecordNormalized_Matchable, z as definePathParamParser } from "../index-D_VEAp3P.js";
//#region src/experimental/route-resolver/matchers/errors.d.ts
/**
* Error throw when a matcher matches by regex but validation fails.
*
* @internal
*/
declare class MatchMiss extends Error {
name: string;
}
/**
* Helper to throw a {@link MatchMiss} error.
* @param args - Arguments to pass to the `MatchMiss` constructor.
*
* @example
* ```ts
* miss()
* // in a number param matcher
* miss('Number must be finite')
* ```
*/
declare const miss: (...args: ConstructorParameters<typeof MatchMiss>) => never;
//#endregion
//#region src/experimental/runtime.d.ts
/**
* Helper to define page properties with file-based routing.
* **Doesn't do anything**, used for types only.
*
* @param route - route information to be added to this page
*
* @internal
*/
declare const definePage: (route: DefinePage) => DefinePage;
/**
* Merges route records.
*
* @internal
*
* @param main - main route record
* @param routeRecords - route records to merge
* @returns merged route record
*/
declare function _mergeRouteRecord(main: RouteRecordRaw, ...routeRecords: Partial<RouteRecordRaw>[]): RouteRecordRaw;
/**
* Type to define a page. Can be augmented to add custom properties.
*/
interface DefinePage extends Partial<Omit<RouteRecordRaw, 'children' | 'components' | 'component' | 'name'>> {
/**
* A route name. If not provided, the name will be generated based on the file path.
* Can be set to `false` to remove the name from types.
*/
name?: string | false;
/**
* Custom parameters for the route. Requires `experimental.paramParsers` enabled.
*
* @experimental
*/
params?: {
path?: Record<string, ParamParserType>;
/**
* Parameters extracted from the query.
*/
query?: Record<string, DefinePageQueryParamOptions | ParamParserType>;
};
}
type ParamParserType_Native = 'int' | 'bool';
type ParamParserType = (TypesConfig extends Record<'ParamParsers', infer ParamParsers> ? ParamParsers : never) | ParamParserType_Native;
/**
* Configures how to extract a route param from a specific query parameter.
*/
interface DefinePageQueryParamOptions<T = unknown> {
/**
* The type of the query parameter. Allowed values are native param parsers
* and any parser in the {@link https://uvr.esm.is/TODO | params folder }. If
* not provided, the value will kept as is.
*/
parser?: ParamParserType;
/**
* Default value if the query parameter is missing or if the match fails
* (e.g. a invalid number is passed to the int param parser). If not provided
* and the param is not required, the route will match with undefined.
*/
default?: (() => T) | T;
/**
* How to format the query parameter value.
*
* - 'value' - keep the first value only and pass that to parser
* - 'array' - keep all values (even one or none) as an array and pass that to parser
*
* @default 'value'
*/
format?: 'value' | 'array';
/**
* Whether this query parameter is required. If true and the parameter is
* missing (and no default is provided), the route will not match.
*
* @default false
*/
required?: boolean;
}
//#endregion
//#region src/experimental/data-loaders/defineLoader.d.ts
/**
* Creates a data loader composable that can be exported by pages to attach the data loading to a route. In this version `data` is always defined.
*
* @param name - name of the route
* @param loader - function that returns a promise with the data
* @param options - options to configure the data loader
*/
declare function defineBasicLoader<Name extends keyof RouteMap, Data>(name: Name, loader: DefineLoaderFn<Data, DataLoaderContext, RouteLocationNormalizedLoaded<Name>>, options?: DefineDataLoaderOptions_DefinedData): UseDataLoaderBasic_DefinedData<Data>;
/**
* Creates a data loader composable that can be exported by pages to attach the data loading to a route. In this version, `data` can be `undefined`.
*
* @param name - name of the route
* @param loader - function that returns a promise with the data
* @param options - options to configure the data loader
*/
declare function defineBasicLoader<Name extends keyof RouteMap, Data>(name: Name, loader: DefineLoaderFn<Data, DataLoaderContext, RouteLocationNormalizedLoaded<Name>>, options: DefineDataLoaderOptions_LaxData): UseDataLoaderBasic_LaxData<Data>;
/**
* Creates a data loader composable that can be exported by pages to attach the data loading to a route. In this version `data` is always defined.
*
* @param loader - function that returns a promise with the data
* @param options - options to configure the data loader
*/
declare function defineBasicLoader<Data>(loader: DefineLoaderFn<Data, DataLoaderContext, RouteLocationNormalizedLoaded>, options?: DefineDataLoaderOptions_DefinedData): UseDataLoaderBasic_DefinedData<Data>;
/**
* Creates a data loader composable that can be exported by pages to attach the data loading to a route. In this version, `data` can be `undefined`.
*
* @param loader - function that returns a promise with the data
* @param options - options to configure the data loader
*/
declare function defineBasicLoader<Data>(loader: DefineLoaderFn<Data, DataLoaderContext, RouteLocationNormalizedLoaded>, options: DefineDataLoaderOptions_LaxData): UseDataLoaderBasic_LaxData<Data>;
interface DefineDataLoaderOptions_LaxData extends DefineDataLoaderOptionsBase_LaxData {
/**
* Key to use for SSR state. This will be used to read the initial data from `initialData`'s object.
*/
key?: string;
}
interface DefineDataLoaderOptions_DefinedData extends DefineDataLoaderOptionsBase_DefinedData {
key?: string;
}
/**
* @deprecated use {@link DefineDataLoaderOptions_LaxData} instead
*/
type DefineDataLoaderOptions = DefineDataLoaderOptions_LaxData;
interface DataLoaderContext extends DataLoaderContextBase {}
/**
* Symbol used to store the data in the router so it can be retrieved after the initial navigation.
* @internal
*/
declare const SERVER_INITIAL_DATA_KEY: unique symbol;
/**
* Initial data generated on server and consumed on client.
* @internal
*/
declare const INITIAL_DATA_KEY: unique symbol;
declare module '../../router' {
interface Router {
/**
* Gives access to the initial state during rendering. Should be set to `false` once it's consumed.
* @internal
*/
[SERVER_INITIAL_DATA_KEY]?: Record<string, unknown> | false;
[INITIAL_DATA_KEY]?: Record<string, unknown> | false;
}
}
interface UseDataLoaderBasic_LaxData<Data> extends UseDataLoader<Data | undefined, ErrorDefault> {}
/**
* @deprecated use {@link UseDataLoaderBasic_LaxData} instead
*/
type UseDataLoaderBasic<Data> = UseDataLoaderBasic_LaxData<Data>;
interface UseDataLoaderBasic_DefinedData<Data> extends UseDataLoader<Data, ErrorDefault> {}
interface DataLoaderBasicEntry<TData, TError = unknown, TDataInitial extends TData | undefined = TData | undefined> extends DataLoaderEntryBase<TData, TError, TDataInitial> {}
//#endregion
//#region src/experimental/index.d.ts
/**
* @deprecated Use {@link reroute} instead.
*/
declare class NavigationResult extends NavigationResult$1 {
constructor(...args: ConstructorParameters<typeof NavigationResult$1>);
}
//#endregion
export { type DataLoaderBasicEntry, type DataLoaderContext, type DataLoaderContextBase, type DataLoaderEntryBase, DataLoaderPlugin, type DataLoaderPluginOptions, type DefineDataLoaderOptions, type DefineDataLoaderOptionsBase_DefinedData, type DefineDataLoaderOptionsBase_LaxData, type DefineDataLoaderOptions_DefinedData, type DefineDataLoaderOptions_LaxData, type DefineLoaderFn, type DefinePage, type DefinePageQueryParamOptions, type EXPERIMENTAL_RouteRecordNormalized, type EXPERIMENTAL_RouteRecordNormalized_Group, type EXPERIMENTAL_RouteRecordNormalized_Matchable, type EXPERIMENTAL_RouteRecordRaw, type EXPERIMENTAL_RouteRecord_Base, type EXPERIMENTAL_RouteRecord_Group, type EXPERIMENTAL_RouteRecord_Matchable, type EXPERIMENTAL_Router, type EXPERIMENTAL_RouterOptions, type EXPERIMENTAL_RouterOptions_Base, type EXPERIMENTAL_Router_Base, type EmptyParams, type ErrorDefault, type MatcherParamsFormatted, type MatcherPattern, type MatcherPatternHash, type MatcherPatternPath, MatcherPatternPathDynamic, type MatcherPatternPathDynamic_ParamOptions, MatcherPatternPathStatic, type MatcherPatternQuery, MatcherPatternQueryParam, type MatcherQueryParams, type MatcherQueryParamsValue, NavigationResult, PARAM_PARSER_BOOL, PARAM_PARSER_INT, type ParamParser, type ParamParserType, type ParamParserType_Native, type SetupLoaderGuardOptions, type UseDataLoader, type UseDataLoaderBasic, type UseDataLoaderBasic_DefinedData, type UseDataLoaderBasic_LaxData, type UseDataLoaderInternals, type UseDataLoaderResult, type ExtractParamParserType as _ExtractParamParserType, MatchMiss as _MatchMiss, NavigationResult$1 as _NavigationResult, _mergeRouteRecord, normalizeParamParser as _normalizeParamParser, createFixedResolver, defineBasicLoader, definePage, defineParamParser, definePathParamParser, defineQueryParamParser, experimental_createRouter, getCurrentContext, miss, normalizeRouteRecord, reroute, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext };
+986
View File
@@ -0,0 +1,986 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { a as routerKey, b as isBrowser, c as ErrorTypes, d as isNavigationFailure, h as isArray$1, i as routeLocationKey, m as identityFn, n as useRouter, o as routerViewLocationKey, p as assign, t as useRoute, u as createRouterError, y as noop } from "../useApi-DtucMc-S.js";
import { A as resolveRelativePath, E as isSameRouteLocation, F as encodeParam, I as encodePath, L as warn$2, N as decode, T as START_LOCATION_NORMALIZED, _ as saveScrollPosition, b as NavigationType, c as useCallbacks, d as stringifyQuery, g as getScrollKey, h as getSavedScrollPosition, i as guardToPromiseFn, k as parseURL, l as normalizeQuery, m as computeScrollPosition, n as extractChangingRecords, r as extractComponentsGuards, t as addDevtools, u as parseQuery, v as scrollToPosition, w as NEW_stringifyURL } from "../devtools-BPov6AZY.js";
import { _ as LOADER_SET_KEY, b as toLazyValue, c as setCurrentContext, d as ABORT_CONTROLLER_KEY, f as APP_KEY, g as LOADER_ENTRIES_KEY, h as IS_USE_DATA_LOADER_KEY, i as useIsDataLoading, l as trackRoute, m as IS_SSR_KEY, n as NavigationResult$1, o as getCurrentContext, r as reroute, t as DataLoaderPlugin, u as withLoaderContext, v as PENDING_LOCATION_KEY, y as STAGED_NO_VALUE } from "../navigation-guard-DK6v16ki.js";
import { nextTick, shallowReactive, shallowRef, toValue, unref, warn } from "vue";
import "scule";
//#region src/experimental/router.ts
function normalizeRouteRecord(record) {
const normalizedRecord = {
meta: {},
props: {},
...record,
instances: {},
leaveGuards: /* @__PURE__ */ new Set(),
updateGuards: /* @__PURE__ */ new Set()
};
Object.defineProperty(normalizedRecord, "mods", { value: {} });
return normalizedRecord;
}
/**
* Creates an experimental Router that allows passing a resolver instead of a
* routes array. This router does not have `addRoute()` and `removeRoute()`
* methods and is meant to be used with file-based routing thanks to
* vue-router/vite or vue-router/unplugin resolver generation in
* `'vue-router/auto-resolver'`.
*
* @param options - Options to initialize the router
*/
function experimental_createRouter(options) {
let { resolver, stringifyQuery: stringifyQuery$1 = stringifyQuery, history: routerHistory } = options;
const beforeGuards = useCallbacks();
const beforeResolveGuards = useCallbacks();
const afterGuards = useCallbacks();
const currentRoute = shallowRef(START_LOCATION_NORMALIZED);
let pendingLocation = START_LOCATION_NORMALIZED;
if (isBrowser && options.scrollBehavior) history.scrollRestoration = "manual";
function resolve(...[to, currentLocation]) {
const matchedRoute = resolver.resolve(to, currentLocation ?? (typeof to === "string" ? currentRoute.value : void 0));
const href = routerHistory.createHref(matchedRoute.fullPath);
if (process.env.NODE_ENV !== "production") {
if (href.startsWith("//")) warn(`Location ${JSON.stringify(to)} resolved to "${href}". A resolved location cannot start with multiple slashes.`);
if (!matchedRoute.matched.length) warn(`No match found for location with path "${to}"`);
}
return assign(matchedRoute, {
redirectedFrom: void 0,
href,
meta: mergeMetaFields(matchedRoute.matched)
});
}
function checkCanceledNavigation(to, from) {
if (pendingLocation !== to) return createRouterError(ErrorTypes.NAVIGATION_CANCELLED, {
from,
to
});
}
const push = (...args) => pushWithRedirect(resolve(...args));
const replace = (...args) => pushWithRedirect(resolve(...args), true);
function handleRedirectRecord(to, from) {
const redirect = to.matched.at(-1)?.redirect;
if (redirect) return resolver.resolve(typeof redirect === "function" ? redirect(to, from) : redirect, from);
}
function pushWithRedirect(to, replace, redirectedFrom) {
replace = to.replace ?? replace;
pendingLocation = to;
const from = currentRoute.value;
const data = to.state;
const force = to.force;
const shouldRedirect = handleRedirectRecord(to, from);
if (shouldRedirect) return pushWithRedirect({
...resolve(shouldRedirect, currentRoute.value),
state: typeof shouldRedirect === "object" ? assign({}, data, shouldRedirect.state) : data,
force
}, replace, redirectedFrom || to);
const toLocation = to;
toLocation.redirectedFrom = redirectedFrom;
let failure;
if (!force && isSameRouteLocation(stringifyQuery$1, from, to)) {
failure = createRouterError(ErrorTypes.NAVIGATION_DUPLICATED, {
to: toLocation,
from
});
handleScroll(from, from, true, false);
}
return (failure ? Promise.resolve(failure) : navigate(toLocation, from)).catch((error) => isNavigationFailure(error) ? isNavigationFailure(error, ErrorTypes.NAVIGATION_GUARD_REDIRECT) ? error : markAsReady(error) : triggerError(error, toLocation, from)).then((failure) => {
if (failure) {
if (isNavigationFailure(failure, ErrorTypes.NAVIGATION_GUARD_REDIRECT)) {
if (process.env.NODE_ENV !== "production" && isSameRouteLocation(stringifyQuery$1, resolve(failure.to), toLocation) && redirectedFrom && (redirectedFrom._count = redirectedFrom._count ? redirectedFrom._count + 1 : 1) > 30) {
warn(`Detected a possibly infinite redirection in a navigation guard when going from "${from.fullPath}" to "${toLocation.fullPath}". Aborting to avoid a Stack Overflow.\n Are you always returning a new location within a navigation guard? That would lead to this error. Only return when redirecting or aborting, that should fix this. This might break in production if not fixed.`);
return Promise.reject(/* @__PURE__ */ new Error("Infinite redirect in navigation guard"));
}
return pushWithRedirect({
...resolve(failure.to, currentRoute.value),
state: typeof failure.to === "object" ? assign({}, data, failure.to.state) : data,
force
}, replace, redirectedFrom || toLocation);
}
} else failure = finalizeNavigation(toLocation, from, true, replace, data);
triggerAfterEach(toLocation, from, failure);
return failure;
});
}
/**
* Helper to reject and skip all navigation guards if a new navigation happened
* @param to
* @param from
*/
function checkCanceledNavigationAndReject(to, from) {
const error = checkCanceledNavigation(to, from);
return error ? Promise.reject(error) : Promise.resolve();
}
function runWithContext(fn) {
const app = installedApps.values().next().value;
return app?.runWithContext ? app.runWithContext(fn) : fn();
}
function navigate(to, from) {
let guards;
const [leavingRecords, updatingRecords, enteringRecords] = extractChangingRecords(to, from);
guards = extractComponentsGuards(leavingRecords.reverse(), "beforeRouteLeave", to, from);
for (const record of leavingRecords) record.leaveGuards.forEach((guard) => {
guards.push(guardToPromiseFn(guard, to, from));
});
const canceledNavigationCheck = checkCanceledNavigationAndReject.bind(null, to, from);
guards.push(canceledNavigationCheck);
return runGuardQueue(guards).then(() => {
guards = [];
for (const guard of beforeGuards.list()) guards.push(guardToPromiseFn(guard, to, from));
guards.push(canceledNavigationCheck);
return runGuardQueue(guards);
}).then(() => {
guards = extractComponentsGuards(updatingRecords, "beforeRouteUpdate", to, from);
for (const record of updatingRecords) record.updateGuards.forEach((guard) => {
guards.push(guardToPromiseFn(guard, to, from));
});
guards.push(canceledNavigationCheck);
return runGuardQueue(guards);
}).then(() => {
guards = [];
for (const record of enteringRecords) if (record.beforeEnter) if (isArray$1(record.beforeEnter)) for (const beforeEnter of record.beforeEnter) guards.push(guardToPromiseFn(beforeEnter, to, from));
else guards.push(guardToPromiseFn(record.beforeEnter, to, from));
guards.push(canceledNavigationCheck);
return runGuardQueue(guards);
}).then(() => {
to.matched.forEach((record) => record.enterCallbacks = {});
guards = extractComponentsGuards(enteringRecords, "beforeRouteEnter", to, from, runWithContext);
guards.push(canceledNavigationCheck);
return runGuardQueue(guards);
}).then(() => {
guards = [];
for (const guard of beforeResolveGuards.list()) guards.push(guardToPromiseFn(guard, to, from));
guards.push(canceledNavigationCheck);
return runGuardQueue(guards);
}).catch((err) => isNavigationFailure(err, ErrorTypes.NAVIGATION_CANCELLED) ? err : Promise.reject(err));
}
function triggerAfterEach(to, from, failure) {
afterGuards.list().forEach((guard) => runWithContext(() => guard(to, from, failure)));
}
/**
* - Cleans up any navigation guards
* - Changes the url if necessary
* - Calls the scrollBehavior
*/
function finalizeNavigation(toLocation, from, isPush, replace, data) {
const error = checkCanceledNavigation(toLocation, from);
if (error) return error;
const isFirstNavigation = from === START_LOCATION_NORMALIZED;
const state = !isBrowser ? {} : history.state;
if (isPush) if (replace || isFirstNavigation) routerHistory.replace(toLocation.fullPath, assign({ scroll: isFirstNavigation && state && state.scroll }, data));
else routerHistory.push(toLocation.fullPath, data);
currentRoute.value = toLocation;
handleScroll(toLocation, from, isPush, isFirstNavigation);
markAsReady();
}
let removeHistoryListener;
function setupListeners() {
if (removeHistoryListener) return;
removeHistoryListener = routerHistory.listen((to, _from, info) => {
if (!router.listening) return;
const toLocation = resolve(to);
const shouldRedirect = handleRedirectRecord(toLocation, router.currentRoute.value);
if (shouldRedirect) {
pushWithRedirect(assign(resolve(shouldRedirect), { force: true }), true, toLocation).catch(noop);
return;
}
pendingLocation = toLocation;
const from = currentRoute.value;
if (isBrowser) saveScrollPosition(getScrollKey(from.fullPath, info.delta), computeScrollPosition());
navigate(toLocation, from).catch((error) => {
if (isNavigationFailure(error, ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_CANCELLED)) return error;
if (isNavigationFailure(error, ErrorTypes.NAVIGATION_GUARD_REDIRECT)) {
pushWithRedirect(assign(resolve(error.to), { force: true }), void 0, toLocation).then((failure) => {
if (isNavigationFailure(failure, ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_DUPLICATED) && !info.delta && info.type === NavigationType.pop) routerHistory.go(-1, false);
}).catch(noop);
return Promise.reject();
}
if (info.delta) routerHistory.go(-info.delta, false);
return triggerError(error, toLocation, from);
}).then((failure) => {
failure = failure || finalizeNavigation(toLocation, from, false);
if (failure) {
if (info.delta && !isNavigationFailure(failure, ErrorTypes.NAVIGATION_CANCELLED)) routerHistory.go(-info.delta, false);
else if (info.type === NavigationType.pop && isNavigationFailure(failure, ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_DUPLICATED)) routerHistory.go(-1, false);
}
triggerAfterEach(toLocation, from, failure);
}).catch(noop);
});
}
let readyHandlers = useCallbacks();
let errorListeners = useCallbacks();
let ready;
/**
* Trigger errorListeners added via onError and throws the error as well
*
* @param error - error to throw
* @param to - location we were navigating to when the error happened
* @param from - location we were navigating from when the error happened
* @returns the error as a rejected promise
*/
function triggerError(error, to, from) {
markAsReady(error);
const list = errorListeners.list();
if (list.length) list.forEach((handler) => handler(error, to, from));
else {
if (process.env.NODE_ENV !== "production") warn("uncaught error during route navigation:");
console.error(error);
}
return Promise.reject(error);
}
function isReady() {
if (ready && currentRoute.value !== START_LOCATION_NORMALIZED) return Promise.resolve();
return new Promise((resolve, reject) => {
readyHandlers.add([resolve, reject]);
});
}
function markAsReady(err) {
if (!ready) {
ready = !err;
setupListeners();
readyHandlers.list().forEach(([resolve, reject]) => err ? reject(err) : resolve());
readyHandlers.reset();
}
return err;
}
function handleScroll(to, from, isPush, isFirstNavigation) {
const { scrollBehavior } = options;
if (!isBrowser || !scrollBehavior) return Promise.resolve();
const scrollPosition = !isPush && getSavedScrollPosition(getScrollKey(to.fullPath, 0)) || (isFirstNavigation || !isPush) && history.state && history.state.scroll || null;
return nextTick().then(() => scrollBehavior(to, from, scrollPosition)).then((position) => position && scrollToPosition(position)).catch((err) => triggerError(err, to, from));
}
const go = (delta) => routerHistory.go(delta);
let started;
const installedApps = /* @__PURE__ */ new Set();
const router = {
currentRoute,
listening: true,
hasRoute: (name) => !!resolver.getRoute(name),
getRoutes: () => resolver.getRoutes(),
resolve,
options,
push,
replace,
go,
back: () => go(-1),
forward: () => go(1),
beforeEach: beforeGuards.add,
beforeResolve: beforeResolveGuards.add,
afterEach: afterGuards.add,
onError: errorListeners.add,
isReady,
install(app) {
app.config.globalProperties.$router = router;
Object.defineProperty(app.config.globalProperties, "$route", {
enumerable: true,
get: () => unref(currentRoute)
});
if (isBrowser && !started && currentRoute.value === START_LOCATION_NORMALIZED) {
started = true;
push(routerHistory.location).catch((err) => {
if (process.env.NODE_ENV !== "production") warn("Unexpected error on initial navigation:", err);
});
}
const reactiveRoute = {};
for (const key in START_LOCATION_NORMALIZED) Object.defineProperty(reactiveRoute, key, {
get: () => currentRoute.value[key],
enumerable: true
});
app.provide(routerKey, router);
app.provide(routeLocationKey, shallowReactive(reactiveRoute));
app.provide(routerViewLocationKey, currentRoute);
installedApps.add(app);
app.onUnmount(() => {
installedApps.delete(app);
if (installedApps.size < 1) {
pendingLocation = START_LOCATION_NORMALIZED;
removeHistoryListener && removeHistoryListener();
removeHistoryListener = null;
currentRoute.value = START_LOCATION_NORMALIZED;
started = false;
ready = false;
}
});
if ((process.env.NODE_ENV !== "production" || __VUE_PROD_DEVTOOLS__) && isBrowser) addDevtools(app, router, resolver);
}
};
function runGuardQueue(guards) {
return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve());
}
if (process.env.NODE_ENV !== "production") router._hmrReplaceResolver = (newResolver) => {
resolver = newResolver;
};
return router;
}
/**
* Merge meta fields of an array of records
*
* @param matched - array of matched records
*/
function mergeMetaFields(matched) {
return assign({}, ...matched.map((r) => r.meta));
}
//#endregion
//#region src/experimental/route-resolver/resolver-abstract.ts
/**
* Common properties for a location that couldn't be matched. This ensures
* having the same name while having a `path`, `query` and `hash` that change.
*/
const NO_MATCH_LOCATION = {
name: process.env.NODE_ENV !== "production" ? Symbol("no-match") : Symbol(),
params: {},
matched: []
};
//#endregion
//#region src/experimental/route-resolver/resolver-fixed.ts
/**
* Build the `matched` array of a record that includes all parent records from the root to the current one.
*/
function buildMatched(record) {
const matched = [];
let node = record;
while (node) {
matched.unshift(node);
node = node.parent;
}
return matched;
}
/**
* Creates a fixed resolver that must have all records defined at creation
* time.
*
* @template TRecord - extended type of the records
* @param {TRecord[]} records - Ordered array of records that will be used to resolve routes
* @returns a resolver that can be passed to the router
*/
function createFixedResolver(records) {
const recordMap = /* @__PURE__ */ new Map();
for (const record of records) if (!record.aliasOf) recordMap.set(record.name, record);
function validateMatch(record, url) {
const pathParams = record.path.match(url.path);
const hashParams = record.hash?.match(url.hash);
const matched = buildMatched(record);
const queryParams = Object.assign({}, ...matched.flatMap((record) => record.query?.map((query) => query.match(url.query))));
return [matched, {
...pathParams,
...queryParams,
...hashParams
}];
}
function resolve(...[to, currentLocation]) {
if (typeof to === "object" && (to.name || to.path == null)) {
if (process.env.NODE_ENV !== "production" && to.name == null && currentLocation == null) {
warn$2(`Cannot resolve relative location "${JSON.stringify(to)}"without a "name" or a current location. This will crash in production.`, to);
const query = normalizeQuery(to.query);
const hash = to.hash ?? "";
const path = to.path ?? "/";
return {
...to,
...NO_MATCH_LOCATION,
fullPath: NEW_stringifyURL(stringifyQuery, path, query, hash),
path,
query,
hash
};
}
const name = to.name ?? currentLocation.name;
const record = recordMap.get(name);
if (process.env.NODE_ENV !== "production") {
if (!record || !name) throw new Error(`Record "${String(name)}" not found`);
if (typeof to === "object" && to.hash && !to.hash.startsWith("#")) warn$2(`A "hash" should always start with the character "#". Replace "${to.hash}" with "#${to.hash}".`);
}
let params = {
...currentLocation?.params,
...to.params
};
const path = record.path.build(params);
const hash = record.hash?.build(params) ?? to.hash ?? currentLocation?.hash ?? "";
let matched = buildMatched(record);
const query = Object.assign({
...currentLocation?.query,
...normalizeQuery(to.query)
}, ...matched.flatMap((record) => record.query?.map((query) => query.build(params))));
const url = {
...to,
fullPath: NEW_stringifyURL(stringifyQuery, path, query, hash),
path,
hash,
query
};
[matched, params] = validateMatch(record, url);
return {
...url,
name,
matched,
params
};
} else {
let url;
if (typeof to === "string") url = parseURL(parseQuery, to, currentLocation?.path);
else {
const query = normalizeQuery(to.query);
const path = resolveRelativePath(to.path, currentLocation?.path || "/");
url = {
...to,
fullPath: NEW_stringifyURL(stringifyQuery, path, query, to.hash),
path,
query,
hash: to.hash || ""
};
}
let record;
let matched;
let parsedParams;
for (record of records) try {
[matched, parsedParams] = validateMatch(record, url);
break;
} catch {}
if (!parsedParams || !matched) return {
...url,
...NO_MATCH_LOCATION
};
return {
...url,
name: record.name,
params: parsedParams,
matched
};
}
}
return {
resolve,
getRoutes: () => records,
getRoute: (name) => recordMap.get(name)
};
}
//#endregion
//#region src/experimental/route-resolver/matchers/errors.ts
/**
* Error throw when a matcher matches by regex but validation fails.
*
* @internal
*/
var MatchMiss = class extends Error {
name = "MatchMiss";
};
/**
* Helper to throw a {@link MatchMiss} error.
* @param args - Arguments to pass to the `MatchMiss` constructor.
*
* @example
* ```ts
* miss()
* // in a number param matcher
* miss('Number must be finite')
* ```
*/
const miss = (...args) => {
throw new MatchMiss(...args);
};
//#endregion
//#region src/experimental/route-resolver/matchers/matcher-pattern.ts
/**
* Allows matching a static path.
*
* @example
* ```ts
* const matcher = new MatcherPatternPathStatic('/team')
* matcher.match('/team') // {}
* matcher.match('/team/123') // throws MatchMiss
* matcher.build() // '/team'
* ```
*/
var MatcherPatternPathStatic = class {
/**
* lowercase version of the path to match against.
* This is used to make the matching case insensitive.
*/
pathi;
constructor(path) {
this.path = path;
this.pathi = path.toLowerCase();
}
match(path) {
if (path.toLowerCase() !== this.pathi) miss();
return {};
}
build() {
return this.path;
}
};
/**
* Regex to remove trailing slashes from a path.
*
* @internal
*/
const TRAILING_SLASHES_RE = /\/*$/;
/**
* Handles the `path` part of a URL with dynamic parameters.
*/
var MatcherPatternPathDynamic = class {
/**
* Cached keys of the {@link params} object.
*/
paramsKeys;
/**
* Creates a new dynamic path matcher.
*
* @param re - regex to match the path against
* @param params - object of param parsers as {@link MatcherPatternPathDynamic_ParamOptions}
* @param pathParts - array of path parts, where strings are static parts, 1 are regular params, and 0 are splat params (not encode slash)
* @param trailingSlash - whether the path should end with a trailing slash, null means "do not care" (for trailing splat params)
*/
constructor(re, params, pathParts, trailingSlash = false) {
this.re = re;
this.params = params;
this.pathParts = pathParts;
this.trailingSlash = trailingSlash;
this.paramsKeys = Object.keys(this.params);
}
match(path) {
if (this.trailingSlash != null && this.trailingSlash === !path.endsWith("/")) miss();
const match = path.match(this.re);
if (!match) miss();
const params = {};
for (var i = 0; i < this.paramsKeys.length; i++) {
var paramName = this.paramsKeys[i];
var [parser, repeatable] = this.params[paramName];
var currentMatch = match[i + 1] ?? null;
var value = repeatable ? (currentMatch?.split("/") || []).map(decode) : decode(currentMatch);
params[paramName] = (parser?.get || identityFn)(value);
}
if (process.env.NODE_ENV !== "production" && Object.keys(params).length !== Object.keys(this.params).length) warn$2(`Regexp matched ${match.length} params, but ${i} params are defined. Found when matching "${path}" against ${String(this.re)}`);
return params;
}
build(params) {
let paramIndex = 0;
let paramName;
let parser;
let repeatable;
let optional;
let value;
const path = "/" + this.pathParts.map((part) => {
if (typeof part === "string") return part;
else if (typeof part === "number") {
paramName = this.paramsKeys[paramIndex++];
[parser, repeatable, optional] = this.params[paramName];
value = (parser?.set || identityFn)(params[paramName]);
if (Array.isArray(value) && !value.length && !optional) miss();
return Array.isArray(value) ? value.map(encodeParam).join("/") : (part ? encodeParam : encodePath)(value);
} else return part.map((subPart) => {
if (typeof subPart === "string") return subPart;
paramName = this.paramsKeys[paramIndex++];
[parser, repeatable, optional] = this.params[paramName];
value = (parser?.set || identityFn)(params[paramName]);
if (process.env.NODE_ENV !== "production" && repeatable) {
warn$2(`Param "${String(paramName)}" is repeatable, but used in a sub segment of the path: "${this.pathParts.join("")}". Repeated params can only be used as a full path segment: "/file/[ids]+/something-else". This will break in production.`);
return Array.isArray(value) ? value.map(encodeParam).join("/") : encodeParam(value);
}
return encodeParam(value);
}).join("");
}).filter(identityFn).join("/");
/**
* If the last part of the path is a splat param and its value is empty, it gets
* filteretd out, resulting in a path that doesn't end with a `/` and doesn't even match
* with the original splat path: e.g. /teams/[...pathMatch] does not match /teams, so it makes
* no sense to build a path it cannot match.
*/
return this.trailingSlash == null ? path + (!value && path.at(-1) !== "/" ? "/" : "") : path.replace(TRAILING_SLASHES_RE, this.trailingSlash ? "/" : "");
}
};
//#endregion
//#region src/experimental/route-resolver/matchers/param-parsers/booleans.ts
const PARAM_BOOLEAN_SINGLE = {
get: (value) => {
if (value === void 0) return void 0;
if (value == null) return true;
const lowercaseValue = value.toLowerCase();
if (lowercaseValue === "true") return true;
if (lowercaseValue === "false") return false;
miss();
},
set: (value) => value == null ? value : String(value)
};
const PARAM_BOOLEAN_REPEATABLE = {
get: (value) => value.map((v) => {
const result = PARAM_BOOLEAN_SINGLE.get(v);
return result === void 0 ? false : result;
}),
set: (value) => value.map((v) => PARAM_BOOLEAN_SINGLE.set(v))
};
/**
* Native Param parser for booleans.
*
* @internal
*/
const PARAM_PARSER_BOOL = {
get: (value) => Array.isArray(value) ? PARAM_BOOLEAN_REPEATABLE.get(value) : PARAM_BOOLEAN_SINGLE.get(value),
set: (value) => Array.isArray(value) ? PARAM_BOOLEAN_REPEATABLE.set(value) : PARAM_BOOLEAN_SINGLE.set(value)
};
//#endregion
//#region src/experimental/route-resolver/matchers/param-parsers/integers.ts
const PARAM_INTEGER_SINGLE = {
get: (value) => {
const num = Number(value);
if (value && Number.isSafeInteger(num)) return num;
miss();
},
set: (value) => String(value)
};
const PARAM_INTEGER_REPEATABLE = {
get: (value) => value.filter((v) => v != null).map(PARAM_INTEGER_SINGLE.get),
set: (value) => value.map(PARAM_INTEGER_SINGLE.set)
};
/**
* Native Param parser for integers.
*
* @internal
*/
const PARAM_PARSER_INT = {
get: (value) => Array.isArray(value) ? PARAM_INTEGER_REPEATABLE.get(value) : value != null ? PARAM_INTEGER_SINGLE.get(value) : null,
set: (value) => Array.isArray(value) ? PARAM_INTEGER_REPEATABLE.set(value) : value != null ? PARAM_INTEGER_SINGLE.set(value) : null
};
//#endregion
//#region src/experimental/route-resolver/matchers/param-parsers/standard-schema.ts
/**
* Normalizes a param parser input, converting a StandardSchema-compliant object
* into a {@link ParamParser} if needed.
*
* @param parser - a param parser or a StandardSchema-compliant validator
*
* @internal
*/
function normalizeParamParser(parser) {
return "~standard" in parser ? { get(value) {
const result = parser["~standard"].validate(value);
if (process.env.NODE_ENV !== "production" && result instanceof Promise) throw new TypeError("async validation is not supported for param parsers");
if (result.issues) miss(result.issues.map((issue) => issue.message).join(", "));
return result.value;
} } : parser;
}
//#endregion
//#region src/experimental/route-resolver/matchers/param-parsers/index.ts
/**
* Default parser for params that will keep values as is, and will use `String()`
*/
const PARAM_PARSER_DEFAULTS = {
get: (value) => value ?? null,
set: (value) => value == null ? null : Array.isArray(value) ? value.map((v) => v == null ? null : String(v)) : String(value)
};
/**
* Defines a path param parser.
*
* @param parser - the parser to define. Will be returned as is.
*
* @see {@link defineQueryParamParser}
* @see {@link defineParamParser}
*/
/*! #__NO_SIDE_EFFECTS__ */
function definePathParamParser(parser) {
return parser;
}
/**
* Defines a query param parser. Note that query params can also be used as
* path param parsers.
*
* @param parser - the parser to define. Will be returned as is.
*
* @see {@link definePathParamParser}
* @see {@link defineParamParser}
*/
/*! #__NO_SIDE_EFFECTS__ */
function defineQueryParamParser(parser) {
return parser;
}
/**
* Alias for {@link defineQueryParamParser}. Implementing a param parser like this
* works for path, query, and hash params.
*
* @see {@link defineQueryParamParser}
* @see {@link definePathParamParser}
*/
const defineParamParser = defineQueryParamParser;
//#endregion
//#region src/experimental/route-resolver/matchers/matcher-pattern-query.ts
/**
* Matcher for a specific query parameter. It will read and write the parameter
*/
var MatcherPatternQueryParam = class {
constructor(paramName, queryKey, format, parser = {}, defaultValue, required) {
this.paramName = paramName;
this.queryKey = queryKey;
this.format = format;
this.parser = parser;
this.defaultValue = defaultValue;
this.required = required;
}
match(query) {
const queryValue = query[this.queryKey];
let valueBeforeParse = this.format === "value" ? Array.isArray(queryValue) ? queryValue.at(-1) : queryValue : Array.isArray(queryValue) ? queryValue : queryValue == null ? [] : [queryValue];
let value;
if (Array.isArray(valueBeforeParse)) if (queryValue === void 0 && this.defaultValue !== void 0) value = toValue(this.defaultValue);
else try {
value = (this.parser.get ?? PARAM_PARSER_DEFAULTS.get)(valueBeforeParse);
} catch (error) {
if (this.defaultValue === void 0) throw error;
value = void 0;
}
else try {
value = valueBeforeParse === void 0 ? valueBeforeParse : (this.parser.get ?? PARAM_PARSER_DEFAULTS.get)(valueBeforeParse);
} catch (error) {
if (this.defaultValue === void 0) throw error;
}
if (value === void 0) {
if (this.defaultValue !== void 0) value = toValue(this.defaultValue);
else if (this.required) miss();
}
return { [this.paramName]: value };
}
build(params) {
const paramValue = params[this.paramName];
if (paramValue === void 0) return {};
return { [this.queryKey]: (this.parser.set ?? PARAM_PARSER_DEFAULTS.set)(paramValue) };
}
};
//#endregion
//#region src/experimental/runtime.ts
/**
* Helper to define page properties with file-based routing.
* **Doesn't do anything**, used for types only.
*
* @param route - route information to be added to this page
*
* @internal
*/
const definePage = (route) => route;
/**
* Merges route records.
*
* @internal
*
* @param main - main route record
* @param routeRecords - route records to merge
* @returns merged route record
*/
function _mergeRouteRecord(main, ...routeRecords) {
return routeRecords.reduce((acc, routeRecord) => {
const meta = Object.assign({}, acc.meta, routeRecord.meta);
const alias = [].concat(acc.alias || [], routeRecord.alias || []);
Object.assign(acc, routeRecord);
acc.meta = meta;
acc.alias = alias;
return acc;
}, main);
}
/**
* TODO: native parsers ideas:
* - json -> just JSON.parse(value)
* - boolean -> 'true' | 'false' -> boolean
* - number -> Number(value) -> NaN if not a number
*/
//#endregion
//#region src/unplugin/core/utils.ts
function warn$1(msg, type = "warn") {
console[type](`⚠️ [vue-router]: ${msg}`);
}
/**
* Type safe alternative to Array.isArray
* https://github.com/microsoft/TypeScript/pull/48228
*/
const isArray = Array.isArray;
//#endregion
//#region src/experimental/data-loaders/defineLoader.ts
function defineBasicLoader(nameOrLoader, _loaderOrOptions, opts) {
const loader = typeof nameOrLoader === "function" ? nameOrLoader : _loaderOrOptions;
opts = typeof _loaderOrOptions === "object" ? _loaderOrOptions : opts;
const options = {
...DEFAULT_DEFINE_LOADER_OPTIONS,
...opts,
commit: opts?.commit || DEFAULT_DEFINE_LOADER_OPTIONS.commit
};
function load(to, router, from, parent) {
const entries = router[LOADER_ENTRIES_KEY];
const isSSR = router[IS_SSR_KEY];
if (!entries.has(loader)) entries.set(loader, {
data: shallowRef(),
isLoading: shallowRef(false),
error: shallowRef(null),
to,
options,
children: /* @__PURE__ */ new Set(),
resetPending() {
this.pendingLoad = null;
this.pendingTo = null;
},
pendingLoad: null,
pendingTo: null,
staged: STAGED_NO_VALUE,
stagedError: null,
commit
});
const entry = entries.get(loader);
if (entry.pendingTo === to && entry.pendingLoad) return entry.pendingLoad;
const { error, isLoading, data } = entry;
const initialRootData = router[INITIAL_DATA_KEY];
const key = options.key || "";
let initialData = STAGED_NO_VALUE;
if (initialRootData && key in initialRootData) {
initialData = initialRootData[key];
delete initialRootData[key];
}
if (initialData !== STAGED_NO_VALUE) {
data.value = initialData;
return entry.pendingLoad = Promise.resolve();
}
entry.pendingTo = to;
isLoading.value = true;
const currentContext = getCurrentContext();
if (process.env.NODE_ENV !== "production") {
if (parent !== currentContext[0]) console.warn(`❌👶 "${options.key}" has a different parent than the current context. This shouldn't be happening. Please report a bug with a reproduction to https://github.com/vuejs/router/`);
}
setCurrentContext([
entry,
router,
to
]);
entry.staged = STAGED_NO_VALUE;
entry.stagedError = error.value;
const currentLoad = Promise.resolve(loader(to, { signal: to.meta[ABORT_CONTROLLER_KEY]?.signal })).then((d) => {
if (entry.pendingLoad === currentLoad) if (d instanceof NavigationResult$1) {
if (process.env.NODE_ENV !== "production") {
console.warn("[vue-router]: Returning a NavigationResult is deprecated. Use reroute() instead, which throws internally.");
warnNonExposedLoader({
to,
options,
useDataLoader
});
}
entry.pendingTo = null;
throw d;
} else {
entry.staged = d;
entry.stagedError = null;
}
}).catch((error) => {
if (entry.pendingLoad === currentLoad) {
if (error instanceof NavigationResult$1) {
if (process.env.NODE_ENV !== "production") warnNonExposedLoader({
to,
options,
useDataLoader
});
entry.pendingTo = null;
throw error;
}
entry.stagedError = error;
if (!toLazyValue(options.lazy, to, from) || isSSR) throw error;
}
}).finally(() => {
setCurrentContext(currentContext);
if (entry.pendingLoad === currentLoad) {
isLoading.value = false;
if (options.commit === "immediate" || !router[PENDING_LOCATION_KEY]) entry.commit(to);
}
});
setCurrentContext(currentContext);
entry.pendingLoad = currentLoad;
return currentLoad;
}
function commit(to) {
if (this.pendingTo === to) {
if (process.env.NODE_ENV !== "production") {
if (this.staged === STAGED_NO_VALUE && this.stagedError === null) console.warn(`Loader "${options.key}"'s "commit()" was called but there is no staged data.`);
}
if (this.staged !== STAGED_NO_VALUE) this.data.value = this.staged;
this.error.value = this.stagedError;
this.staged = STAGED_NO_VALUE;
this.stagedError = this.error.value;
this.pendingTo = null;
this.to = to;
for (const childEntry of this.children) childEntry.commit(to);
}
}
const useDataLoader = () => {
const currentContext = getCurrentContext();
const [parentEntry, _router, _route] = currentContext;
const router = _router || useRouter();
const route = _route || useRoute();
const entries = router[LOADER_ENTRIES_KEY];
let entry = entries.get(loader);
if (!entry || parentEntry && entry.pendingTo !== route || !entry.pendingLoad) router[APP_KEY].runWithContext(() => load(route, router, void 0, parentEntry));
entry = entries.get(loader);
if (parentEntry) {
if (parentEntry === entry) console.warn(`👶❌ "${options.key}" has itself as parent. This shouldn't be happening. Please report a bug with a reproduction to https://github.com/vuejs/router/`);
parentEntry.children.add(entry);
}
const { data, error, isLoading } = entry;
const useDataLoaderResult = {
data,
error,
isLoading,
reload: (to = router.currentRoute.value) => router[APP_KEY].runWithContext(() => load(to, router)).then(() => entry.commit(to))
};
const promise = entry.pendingLoad.then(() => entry.staged === STAGED_NO_VALUE ? data.value : entry.staged).catch((e) => parentEntry ? Promise.reject(e) : null).finally(() => setCurrentContext(currentContext));
setCurrentContext(currentContext);
return Object.assign(promise, useDataLoaderResult);
};
useDataLoader[IS_USE_DATA_LOADER_KEY] = true;
useDataLoader._ = {
load,
options,
getEntry(router) {
return router[LOADER_ENTRIES_KEY].get(loader);
}
};
return useDataLoader;
}
/**
* Dev only warning for loaders that return/throw NavigationResult but are not exposed
*
* @param to - target location
* @param options - options used to define the loader
* @param useDataLoader - the data loader composable
*/
function warnNonExposedLoader({ to, options, useDataLoader }) {
const loaders = to.meta[LOADER_SET_KEY];
if (loaders && !loaders.has(useDataLoader)) warn$1("A loader returned a NavigationResult but is not registered on the route. Did you forget to \"export\" it from the page component?" + (options.key ? ` (loader key: "${options.key}")` : ""));
}
const DEFAULT_DEFINE_LOADER_OPTIONS = {
lazy: false,
server: true,
commit: "after-load"
};
/**
* Initial data generated on server and consumed on client.
* @internal
*/
const INITIAL_DATA_KEY = Symbol();
//#endregion
//#region src/experimental/index.ts
/**
* @deprecated Use {@link reroute} instead.
*/
var NavigationResult = class extends NavigationResult$1 {
constructor(...args) {
super(...args);
console.warn(`[vue-router]: new NavigationResult(to) is deprecated. Use reroute(to) instead.`);
}
};
//#endregion
export { DataLoaderPlugin, MatcherPatternPathDynamic, MatcherPatternPathStatic, MatcherPatternQueryParam, NavigationResult, PARAM_PARSER_BOOL, PARAM_PARSER_INT, MatchMiss as _MatchMiss, NavigationResult$1 as _NavigationResult, _mergeRouteRecord, normalizeParamParser as _normalizeParamParser, createFixedResolver, defineBasicLoader, definePage, defineParamParser, definePathParamParser, defineQueryParamParser, experimental_createRouter, getCurrentContext, miss, normalizeRouteRecord, reroute, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext };
+153
View File
@@ -0,0 +1,153 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { _ as _PromiseMerged, a as DefineLoaderFn, c as UseDataLoaderResult, i as DefineDataLoaderOptionsBase_LaxData, n as DataLoaderEntryBase, o as UseDataLoader, p as NavigationResult, r as DefineDataLoaderOptionsBase_DefinedData, t as DataLoaderContextBase, u as ErrorDefault } from "../index-ZwgQvn2r.js";
import { Ln as LocationQuery, Nt as RouteLocationNormalizedLoaded, rn as RouteMap } from "../index-D_VEAp3P.js";
import { ShallowRef } from "vue";
import { EntryKey, UseQueryOptions, UseQueryReturn } from "@pinia/colada";
//#region src/experimental/data-loaders/defineColadaLoader.d.ts
/**
* Creates a Pinia Colada data loader with `data` is always defined.
*
* @param name - name of the route to have typed routes
* @param options - options to configure the data loader
*/
declare function defineColadaLoader<Name extends keyof RouteMap, Data>(name: Name, options: DefineDataColadaLoaderOptions_DefinedData<Name, Data>): UseDataLoaderColada_DefinedData<Data>;
/**
* Creates a Pinia Colada data loader with `data` is possibly `undefined`.
*
* @param name - name of the route to have typed routes
* @param options - options to configure the data loader
*/
declare function defineColadaLoader<Name extends keyof RouteMap, Data>(name: Name, options: DefineDataColadaLoaderOptions_LaxData<Name, Data>): UseDataLoaderColada_LaxData<Data>;
/**
* Creates a Pinia Colada data loader with `data` is always defined.
* @param options - options to configure the data loader
*/
declare function defineColadaLoader<Data>(options: DefineDataColadaLoaderOptions_DefinedData<keyof RouteMap, Data>): UseDataLoaderColada_DefinedData<Data>;
/**
* Creates a Pinia Colada data loader with `data` is possibly `undefined`.
* @param options - options to configure the data loader
*/
declare function defineColadaLoader<Data>(options: DefineDataColadaLoaderOptions_LaxData<keyof RouteMap, Data>): UseDataLoaderColada_LaxData<Data>;
/**
* Base type with docs for the options of `defineColadaLoader`.
* @internal
*/
interface _DefineDataColadaLoaderOptions_Common<Name extends keyof RouteMap, Data> extends Omit<UseQueryOptions<Data, ErrorDefault, Data>, 'query' | 'key'> {
/**
* Key associated with the data and passed to pinia colada
* @param to - Route to load the data
*/
key: EntryKey | ((to: RouteLocationNormalizedLoaded<Name>) => EntryKey);
/**
* Function that returns a promise with the data.
*/
query: DefineLoaderFn<Data, DataColadaLoaderContext, RouteLocationNormalizedLoaded<Name>>;
}
/**
* Options for `defineColadaLoader` when the data is possibly `undefined`.
*/
interface DefineDataColadaLoaderOptions_LaxData<Name extends keyof RouteMap, Data> extends _DefineDataColadaLoaderOptions_Common<Name, Data>, DefineDataLoaderOptionsBase_LaxData {}
/**
* Options for `defineColadaLoader` when the data is always defined.
*/
interface DefineDataColadaLoaderOptions_DefinedData<Name extends keyof RouteMap, Data> extends _DefineDataColadaLoaderOptions_Common<Name, Data>, DefineDataLoaderOptionsBase_DefinedData {}
/**
* @deprecated Use {@link `DefineDataColadaLoaderOptions_LaxData`} instead.
*/
type DefineDataColadaLoaderOptions<Name extends keyof RouteMap, Data> = DefineDataColadaLoaderOptions_LaxData<Name, Data>;
/**
* @internal
*/
interface DataColadaLoaderContext extends DataLoaderContextBase {}
interface UseDataLoaderColadaResult<TData, TError = ErrorDefault, TDataInitial extends TData | undefined = TData | undefined> extends UseDataLoaderResult<TData | TDataInitial, ErrorDefault>, Pick<UseQueryReturn<TData, TError, TDataInitial>, 'isPending' | 'status' | 'asyncStatus' | 'state'> {
/**
* Equivalent to `useQuery().refetch()`. Refetches the data no matter if its stale or not.
* @see reload - It also calls `refetch()` but returns an empty promise
*/
refetch: (to?: RouteLocationNormalizedLoaded) => ReturnType<UseQueryReturn<TData, TError, TDataInitial>['refetch']>;
/**
* Equivalent to `useQuery().refresh()`. Refetches the data **only** if it's stale.
*/
refresh: (to?: RouteLocationNormalizedLoaded) => ReturnType<UseQueryReturn<TData, TError, TDataInitial>['refetch']>;
}
/**
* Data Loader composable returned by `defineColadaLoader()`.
*/
interface UseDataLoaderColada_LaxData<Data> extends UseDataLoader<Data | undefined, ErrorDefault> {
/**
* Data Loader composable returned by `defineColadaLoader()`.
*
* @example
* Returns the Data loader data, isLoading, error etc. Meant to be used in `setup()` or `<script setup>` **without `await`**:
* ```vue
* <script setup>
* const { data, isLoading, error } = useUserData()
* </script>
* ```
*
* @example
* It also returns a promise of the data when used in nested loaders. Note this `data` is **not a ref**. This is not meant to be used in `setup()` or `<script setup>`.
* ```ts
* export const useUserConnections = defineLoader(async () => {
* const user = await useUserData()
* return fetchUserConnections(user.id)
* })
* ```
*/
(): _PromiseMerged<Exclude<Data, NavigationResult | undefined>, UseDataLoaderColadaResult<Exclude<Data, NavigationResult> | undefined>>;
}
/**
* Data Loader composable returned by `defineColadaLoader()`.
*/
interface UseDataLoaderColada_DefinedData<TData> extends UseDataLoader<TData, ErrorDefault> {
/**
* Data Loader composable returned by `defineColadaLoader()`.
*
* @example
* Returns the Data loader data, isLoading, error etc. Meant to be used in `setup()` or `<script setup>` **without `await`**:
* ```vue
* <script setup>
* const { data, isLoading, error } = useUserData()
* </script>
* ```
*
* @example
* It also returns a promise of the data when used in nested loaders. Note this `data` is **not a ref**. This is not meant to be used in `setup()` or `<script setup>`.
* ```ts
* export const useUserConnections = defineLoader(async () => {
* const user = await useUserData()
* return fetchUserConnections(user.id)
* })
* ```
*/
(): _PromiseMerged<Exclude<TData, NavigationResult | undefined>, UseDataLoaderColadaResult<Exclude<TData, NavigationResult>, ErrorDefault, Exclude<TData, NavigationResult>>>;
}
interface DataLoaderColadaEntry<TData, TError = unknown, TDataInitial extends TData | undefined = TData | undefined> extends DataLoaderEntryBase<TData, TError, TDataInitial> {
/**
* Reactive route passed to pinia colada so it automatically refetch
*/
route: ShallowRef<RouteLocationNormalizedLoaded>;
/**
* Tracked routes to know when the data should be refreshed. Key is the key of the query.
*/
tracked: Map<string, TrackedRoute>;
/**
* Extended options for pinia colada
*/
ext: UseQueryReturn<TData, TError, TDataInitial> | null;
}
interface TrackedRoute {
ready: boolean;
params: Partial<LocationQuery>;
query: Partial<LocationQuery>;
hash: {
v: string | null;
};
}
//#endregion
export { type DataColadaLoaderContext, type DataLoaderColadaEntry, type DefineDataColadaLoaderOptions, type DefineDataColadaLoaderOptions_DefinedData, type DefineDataColadaLoaderOptions_LaxData, type UseDataLoaderColadaResult, type UseDataLoaderColada_DefinedData, type UseDataLoaderColada_LaxData, type _DefineDataColadaLoaderOptions_Common, defineColadaLoader };
+234
View File
@@ -0,0 +1,234 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { n as useRouter, t as useRoute } from "../useApi-DtucMc-S.js";
import { a as assign, b as toLazyValue, c as setCurrentContext, d as ABORT_CONTROLLER_KEY, f as APP_KEY, g as LOADER_ENTRIES_KEY, h as IS_USE_DATA_LOADER_KEY, l as trackRoute, m as IS_SSR_KEY, n as NavigationResult, o as getCurrentContext, p as DATA_LOADERS_EFFECT_SCOPE_KEY, s as isSubsetOf, v as PENDING_LOCATION_KEY, y as STAGED_NO_VALUE } from "../navigation-guard-DK6v16ki.js";
import { shallowRef, watch } from "vue";
import { defineQuery, useQuery, useQueryCache } from "@pinia/colada";
//#region src/experimental/data-loaders/defineColadaLoader.ts
function defineColadaLoader(nameOrOptions, _options) {
_options = _options || nameOrOptions;
const loader = _options.query;
const options = {
...DEFAULT_DEFINE_LOADER_OPTIONS,
..._options,
commit: _options?.commit || "after-load"
};
let isInitial = true;
const useDefinedQuery = defineQuery(() => {
const router = useRouter();
const entry = router[LOADER_ENTRIES_KEY].get(loader);
return useQuery({
...options,
query: () => {
const route = entry.route.value;
const [trackedRoute, params, query, hash] = trackRoute(route);
entry.tracked.set(joinKeys(serializeQueryKey(options.key, trackedRoute)), {
ready: false,
params,
query,
hash
});
return router[APP_KEY].runWithContext(() => loader(trackedRoute, { signal: route.meta[ABORT_CONTROLLER_KEY]?.signal }));
},
key: () => toValueWithParameters(options.key, entry.route.value)
});
});
function load(to, router, from, parent, reload) {
const entries = router[LOADER_ENTRIES_KEY];
const isSSR = router[IS_SSR_KEY];
const key = serializeQueryKey(options.key, to);
if (!entries.has(loader)) {
const route = shallowRef(to);
entries.set(loader, {
data: shallowRef(),
isLoading: shallowRef(false),
error: shallowRef(null),
to,
options,
children: /* @__PURE__ */ new Set(),
resetPending() {
this.pendingTo = null;
this.pendingLoad = null;
this.isLoading.value = false;
},
staged: STAGED_NO_VALUE,
stagedError: null,
commit,
tracked: /* @__PURE__ */ new Map(),
ext: null,
route,
pendingTo: null,
pendingLoad: null
});
}
const entry = entries.get(loader);
if (entry.pendingTo === to && entry.pendingLoad) return entry.pendingLoad;
const currentContext = getCurrentContext();
if (process.env.NODE_ENV !== "production") {
if (parent !== currentContext[0]) console.warn(`❌👶 "${key}" has a different parent than the current context. This shouldn't be happening. Please report a bug with a reproduction to https://github.com/vuejs/router/`);
}
setCurrentContext([
entry,
router,
to
]);
if (!entry.ext) {
entry.ext = useDefinedQuery();
useQueryCache().get(toValueWithParameters(options.key, to))?.deps.delete(router[DATA_LOADERS_EFFECT_SCOPE_KEY]);
reload = false;
}
const { isLoading, data, error, ext } = entry;
if (isInitial) {
isInitial = false;
if (ext.data.value !== void 0) {
data.value = ext.data.value;
setCurrentContext(currentContext);
return entry.pendingLoad = Promise.resolve();
}
}
if (entry.route.value !== to) {
const tracked = entry.tracked.get(joinKeys(key));
reload = !tracked || hasRouteChanged(to, tracked);
}
entry.route.value = entry.pendingTo = to;
isLoading.value = true;
entry.staged = STAGED_NO_VALUE;
entry.stagedError = error.value;
const currentLoad = ext[reload ? "refetch" : "refresh"]().then(() => {
if (entry.pendingLoad === currentLoad) {
const newError = ext.error.value;
if (newError) {
if (newError instanceof NavigationResult) {
entry.pendingTo = null;
throw newError;
}
entry.stagedError = newError;
if (!toLazyValue(options.lazy, to, from) || isSSR) throw newError;
} else {
const newData = ext.data.value;
if (newData instanceof NavigationResult) {
if (process.env.NODE_ENV !== "production") console.warn("[vue-router]: Returning a NavigationResult is deprecated. Use reroute() instead, which throws internally.");
entry.pendingTo = null;
throw newData;
} else {
entry.staged = newData;
entry.stagedError = null;
}
}
}
}).finally(() => {
setCurrentContext(currentContext);
if (entry.pendingLoad === currentLoad) {
isLoading.value = false;
if (options.commit === "immediate" || !router[PENDING_LOCATION_KEY]) entry.commit(to);
}
});
setCurrentContext(currentContext);
entry.pendingLoad = currentLoad;
return currentLoad;
}
function commit(to) {
const key = serializeQueryKey(options.key, to);
if (this.pendingTo === to) {
if (process.env.NODE_ENV !== "production") {
if (this.staged === STAGED_NO_VALUE && this.stagedError === null) console.warn(`Loader "${key}"'s "commit()" was called but there is no staged data.`);
}
if (this.staged !== STAGED_NO_VALUE) {
this.data.value = this.staged;
if (process.env.NODE_ENV !== "production" && !this.tracked.has(joinKeys(key))) {
console.warn(`A query was defined with the same key as the loader "[${key.join(", ")}]". If the "key" is meant to be the same, you should directly use the data loader instead. If not, change the key of the "useQuery()".\nSee https://pinia-colada.esm.dev/#TODO`);
return;
}
this.tracked.get(joinKeys(key)).ready = true;
}
this.error.value = this.stagedError;
this.staged = STAGED_NO_VALUE;
this.stagedError = this.error.value;
this.to = to;
this.pendingTo = null;
for (const childEntry of this.children) childEntry.commit(to);
}
}
const useDataLoader = () => {
const currentContext = getCurrentContext();
const [parentEntry, _router, _route] = currentContext;
const router = _router || useRouter();
const route = _route || useRoute();
const app = router[APP_KEY];
const entries = router[LOADER_ENTRIES_KEY];
let entry = entries.get(loader);
if (!entry || parentEntry && entry.pendingTo !== route || !entry.pendingLoad) app.runWithContext(() => load(route, router, void 0, parentEntry, true));
entry = entries.get(loader);
if (parentEntry) {
if (parentEntry !== entry) parentEntry.children.add(entry);
}
const { data, error, isLoading } = entry;
const ext = useDefinedQuery();
useQueryCache().get(toValueWithParameters(options.key, route))?.deps.delete(router[DATA_LOADERS_EFFECT_SCOPE_KEY]);
watch(ext.data, (newData) => {
if (!router[PENDING_LOCATION_KEY]) data.value = newData;
});
watch(ext.isLoading, (isFetching) => {
if (!router[PENDING_LOCATION_KEY]) isLoading.value = isFetching;
});
watch(ext.error, (newError) => {
if (!router[PENDING_LOCATION_KEY]) error.value = newError;
});
const useDataLoaderResult = {
data,
error,
isLoading,
reload: (to = router.currentRoute.value) => app.runWithContext(() => load(to, router, void 0, void 0, true)).then(() => entry.commit(to)),
refetch: (to = router.currentRoute.value) => app.runWithContext(() => load(to, router, void 0, void 0, true)).then(() => (entry.commit(to), entry.ext.state.value)),
refresh: (to = router.currentRoute.value) => app.runWithContext(() => load(to, router)).then(() => (entry.commit(to), entry.ext.state.value)),
status: ext.status,
asyncStatus: ext.asyncStatus,
state: ext.state,
isPending: ext.isPending
};
const promise = entry.pendingLoad.then(() => entry.staged === STAGED_NO_VALUE ? ext.data.value : entry.staged).catch((e) => parentEntry ? Promise.reject(e) : null).finally(() => setCurrentContext(currentContext));
setCurrentContext(currentContext);
return assign(promise, useDataLoaderResult);
};
useDataLoader[IS_USE_DATA_LOADER_KEY] = true;
useDataLoader._ = {
load,
options,
getEntry(router) {
return router[LOADER_ENTRIES_KEY].get(loader);
}
};
return useDataLoader;
}
const joinKeys = (keys) => keys.join("|");
function hasRouteChanged(to, tracked) {
return !tracked.ready || !isSubsetOf(tracked.params, to.params) || !isSubsetOf(tracked.query, to.query) || tracked.hash.v != null && tracked.hash.v !== to.hash;
}
const DEFAULT_DEFINE_LOADER_OPTIONS = {
lazy: false,
server: true,
commit: "after-load"
};
const toValueWithParameters = (optionValue, arg) => {
return typeof optionValue === "function" ? optionValue(arg) : optionValue;
};
/**
* Transform the key to a string array so it can be used as a key in caches.
*
* @param key - key to transform
* @param to - route to use
*/
function serializeQueryKey(keyOption, to) {
const key = toValueWithParameters(keyOption, to);
return (Array.isArray(key) ? key : [key]).map(stringifyFlatObject);
}
function stringifyFlatObject(obj) {
return obj && typeof obj === "object" ? JSON.stringify(obj, Object.keys(obj).sort()) : String(obj);
}
//#endregion
export { defineColadaLoader };
+2425
View File
File diff suppressed because it is too large Load Diff
+475
View File
@@ -0,0 +1,475 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { Ln as LocationQuery, Nt as RouteLocationNormalizedLoaded, Pt as RouteLocationNormalizedLoadedGeneric, Un as TypesConfig, dn as RouteLocationMatched, hn as RouteMeta, qt as RouteRecordNameGeneric, st as NavigationGuard, vn as RouteParamsGeneric, vt as RouteLocation, y as Router } from "./index-D_VEAp3P.js";
import { App, EffectScope, InjectionKey, ShallowRef } from "vue";
//#region src/experimental/data-loaders/symbols.d.ts
/**
* Retrieves the internal version of loaders.
* @internal
*/
declare const LOADER_SET_KEY: unique symbol;
/**
* Retrieves the internal version of loader entries.
* @internal
*/
declare const LOADER_ENTRIES_KEY: unique symbol;
/**
* Added to the loaders returned by `defineLoader()` to identify them.
* Allows to extract exported useData() from a component.
* @internal
*/
declare const IS_USE_DATA_LOADER_KEY: unique symbol;
/**
* Symbol used to save the pending location on the router.
* @internal
*/
declare const PENDING_LOCATION_KEY: unique symbol;
/**
* Symbol used to know there is no value staged for the loader and that commit should be skipped.
* @internal
*/
declare const STAGED_NO_VALUE: unique symbol;
/**
* Gives access to the current app and it's `runWithContext` method.
* @internal
*/
declare const APP_KEY: unique symbol;
/**
* Gives access to an AbortController that aborts when the navigation is canceled.
* @internal
*/
declare const ABORT_CONTROLLER_KEY: unique symbol;
/**
* Symbol used to save the initial data on the router.
* @internal
*/
declare const IS_SSR_KEY: unique symbol;
/**
* Symbol used to get the effect scope used for data loaders.
* @internal
*/
declare const DATA_LOADERS_EFFECT_SCOPE_KEY: unique symbol;
//#endregion
//#region src/experimental/data-loaders/meta-extensions.d.ts
/**
* Map type for the entries used by data loaders.
* @internal
*/
type _DefineLoaderEntryMap<DataLoaderEntry extends DataLoaderEntryBase<unknown> = DataLoaderEntryBase<unknown>> = WeakMap<object, DataLoaderEntry>;
declare module '../../router' {
interface Router {
/**
* The entries used by data loaders. Put on the router for convenience.
* @internal
*/
[LOADER_ENTRIES_KEY]: _DefineLoaderEntryMap;
/**
* Pending navigation that is waiting for data loaders to resolve.
* @internal
*/
[PENDING_LOCATION_KEY]: RouteLocationNormalizedLoaded | null;
/**
* The app instance that is used by the router.
* @internal
*/
[APP_KEY]: App<unknown>;
/**
* Whether the router is running in server-side rendering mode.
* @internal
*/
[IS_SSR_KEY]: boolean;
/**
* The effect scope used to run data loaders.
* @internal
*/
[DATA_LOADERS_EFFECT_SCOPE_KEY]: EffectScope;
}
}
declare module '../../types' {
interface RouteMeta {
/**
* The data loaders for a route record. Add any data loader to this array to have it called when the route is
* navigated to. Note this is only needed when **not** using lazy components (`() => import('./pages/Home.vue')`) or
* when not explicitly exporting data loaders from page components.
*/
loaders?: UseDataLoader[];
/**
* Set of loaders for the current route. This is built once during navigation and is used to merge the loaders from
* the lazy import in components or the `loaders` array in the route record.
* @internal
*/
[LOADER_SET_KEY]?: Set<UseDataLoader>;
/**
* The signal that is aborted when the navigation is canceled or an error occurs.
* @internal
*/
[ABORT_CONTROLLER_KEY]?: AbortController;
}
}
//#endregion
//#region src/experimental/data-loaders/utils.d.ts
/**
* @internal: data loaders authoring only. Use `getCurrentContext` instead.
*/
declare let currentContext: readonly [entry: DataLoaderEntryBase, router: Router, route: RouteLocationNormalizedLoaded] | undefined | null;
declare function getCurrentContext(): readonly [entry: DataLoaderEntryBase<unknown, unknown, unknown>, router: Router, route: RouteLocationNormalizedLoadedGeneric] | readonly [];
/**
* Sets the current context for data loaders. This allows for nested loaders to be aware of their parent context.
* INTERNAL ONLY.
*
* @param context - the context to set
* @internal
*/
declare function setCurrentContext(context?: typeof currentContext | readonly []): void;
/**
* Restore the current context after a promise is resolved.
* @param promise - promise to wrap
*/
declare function withLoaderContext<P extends Promise<unknown>>(promise: P): P;
/**
* Object and promise of the object itself. Used when we can await some of the properties of an object to be loaded.
* @internal
*/
type _PromiseMerged<PromiseType, RawType = PromiseType> = RawType & Promise<PromiseType>;
/**
* Track the reads of a route and its properties
* @internal
* @param route - route to track
*/
declare function trackRoute(route: RouteLocationNormalizedLoaded): readonly [{
readonly hash: string;
readonly params: RouteParamsGeneric;
readonly query: LocationQuery;
readonly matched: RouteLocationMatched[];
readonly name: RouteRecordNameGeneric;
readonly fullPath: string;
readonly redirectedFrom: RouteLocation | undefined;
readonly meta: RouteMeta;
readonly path: string;
}, Partial<RouteParamsGeneric>, Partial<LocationQuery>, {
v: string | null;
}];
//#endregion
//#region src/experimental/data-loaders/navigation-guard.d.ts
/**
* Options to initialize the data loader guard.
*/
interface SetupLoaderGuardOptions extends DataLoaderPluginOptions {
/**
* The Vue app instance. Used to access the `provide` and `inject` APIs.
*/
app: App<unknown>;
/**
* The effect scope to use for the data loaders.
*/
effect: EffectScope;
}
/**
* Possible values to change the result of a navigation within a loader
* @internal
*/
type _DataLoaderRedirectResult = Exclude<ReturnType<NavigationGuard>, Promise<unknown> | Function | true | void | undefined>;
/**
* Allows data loaders to change navigation. Called by {@link reroute}.
*
* @internal
*/
declare class NavigationResult {
readonly value: _DataLoaderRedirectResult;
constructor(value: _DataLoaderRedirectResult);
}
/**
* Changes the navigation from within a data loader. Accepts the same values as a navigation
* guard return: a route location to redirect to, or `false` to cancel the navigation.
*
* @example
* ```ts
* export const useUserData = defineBasicLoader(async (to) => {
* const user = await fetchUser(to.params.id)
* if (!user) {
* reroute('/404')
* }
* return user
* })
* ```
*/
declare function reroute(to: _DataLoaderRedirectResult): never;
/**
* Data Loader plugin to add data loading support to Vue Router.
*
* @example
* ```ts
* const router = createRouter({
* routes,
* history: createWebHistory(),
* })
*
* const app = createApp({})
* app.use(DataLoaderPlugin, { router })
* app.use(router)
* ```
*/
declare function DataLoaderPlugin(app: App, options: DataLoaderPluginOptions): void;
/**
* Options passed to the DataLoaderPlugin.
*/
interface DataLoaderPluginOptions {
/**
* The router instance. Adds the guards to it
*/
router: Router;
isSSR?: boolean;
/**
* List of _expected_ errors that shouldn't abort the navigation (for non-lazy loaders). Provide a list of
* constructors that can be checked with `instanceof` or a custom function that returns `true` for expected errors.
*/
errors?: Array<new (...args: any) => any> | ((reason?: unknown) => boolean);
}
/**
* Return a ref that reflects the global loading state of all loaders within a navigation.
* This state doesn't update if `refresh()` is manually called.
*/
declare function useIsDataLoading(): ShallowRef<boolean>;
//#endregion
//#region src/experimental/data-loaders/types-config.d.ts
/**
* The default error type used for data loaders. Can be customized via {@link TypesConfig}.
*
* @example
* ```ts
* // types-extension.d.ts
* import 'vue-router/experimental'
* export {}
* declare module 'vue-router/experimental' {
* interface TypesConfig {
* Error: MyCustomError
* }
* }
* ```
*
* @internal
*/
type ErrorDefault = TypesConfig extends Record<'Error', infer E> ? E : Error;
//#endregion
//#region src/experimental/data-loaders/createDataLoader.d.ts
/**
* Base type for a data loader entry. Each Data Loader has its own entry in the `loaderEntries` (accessible via `[LOADER_ENTRIES_KEY]`) map.
*/
interface DataLoaderEntryBase<TData = unknown, TError = unknown, TDataInitial extends TData | undefined = TData | undefined> {
/**
* Data stored in the entry.
*/
data: ShallowRef<TData | TDataInitial>;
/**
* Error if there was an error.
*/
error: ShallowRef<TError | null>;
/**
* Location the data was loaded for or `null` if the data is not loaded.
*/
to: RouteLocationNormalizedLoaded | null;
/**
* Whether there is an ongoing request.
*/
isLoading: ShallowRef<boolean>;
options: DefineDataLoaderOptionsBase_LaxData;
/**
* 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.
*/
resetPending: () => void;
/**
* The latest pending load. Allows to verify if the load is still valid when it resolves.
*/
pendingLoad: Promise<void> | null;
/**
* The latest pending navigation's `to` route. Used to verify if the navigation is still valid when it resolves.
*/
pendingTo: RouteLocationNormalizedLoaded | null;
/**
* Data that was staged by a loader. This is used to avoid showing the old data while the new data is loading. Calling
* the internal `commit()` function will replace the data with the staged data.
*/
staged: TData | typeof STAGED_NO_VALUE;
/**
* Error that was staged by a loader. This is used to avoid showing the old error while the new data is loading.
* Calling the internal `commit()` function will replace the error with the staged error.
*/
stagedError: TError | null;
/**
* Other data loaders that depend on this one. This is used to invalidate the data when a dependency is invalidated.
*/
children: Set<DataLoaderEntryBase>;
/**
* Commits the pending data to the entry. This is called by the navigation guard when all non-lazy loaders have
* finished loading. It should be implemented by the loader. It **must be called** from the entry itself:
* `entry.commit(to)`.
*/
commit(to: RouteLocationNormalizedLoaded): void;
}
/**
* Common properties for the options of `defineLoader()`. Types are `unknown` to allow for more specific types in the
* extended types while having documentation in one single place.
* @internal
*/
interface _DefineDataLoaderOptionsBase_Common {
/**
* When the data should be committed to the entry. In the case of lazy loaders, the loader will try to commit the data
* after all non-lazy loaders have finished loading, but it might not be able to if the lazy loader hasn't been
* resolved yet.
*
* @see {@link DefineDataLoaderCommit}
* @defaultValue `'after-load'`
*/
commit?: DefineDataLoaderCommit;
/**
* 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.
*
* @defaultValue `false`
*/
lazy?: unknown;
/**
* Whether this loader should be awaited on the server side or not. Combined with the `lazy` option, this gives full
* control over how to await for the data.
*
* @defaultValue `true`
*/
server?: unknown;
/**
* List of _expected_ errors that shouldn't abort the navigation (for non-lazy loaders). Provide a list of
* constructors that can be checked with `instanceof` or a custom function that returns `true` for expected errors. Can also be set to `true` to accept all globally defined errors. Defaults to `false` to abort on any error.
* @default `false`
*/
errors?: unknown;
}
/**
* Options for a data loader that returns a data that is possibly `undefined`. Available for data loaders
* implementations so they can be used in `defineLoader()` overloads.
*/
interface DefineDataLoaderOptionsBase_LaxData extends _DefineDataLoaderOptionsBase_Common {
lazy?: boolean | ((to: RouteLocationNormalizedLoaded, from?: RouteLocationNormalizedLoaded) => boolean);
server?: boolean;
errors?: boolean | Array<new (...args: any[]) => any> | ((reason?: unknown) => boolean);
}
/**
* Options for a data loader making the data defined without it being possibly `undefined`. Available for data loaders
* implementations so they can be used in `defineLoader()` overloads.
*/
interface DefineDataLoaderOptionsBase_DefinedData extends _DefineDataLoaderOptionsBase_Common {
lazy?: false;
server?: true;
errors?: false;
}
declare const toLazyValue: (lazy: undefined | DefineDataLoaderOptionsBase_LaxData["lazy"], to: RouteLocationNormalizedLoaded, from?: RouteLocationNormalizedLoaded) => boolean | undefined;
/**
* When the data should be committed to the entry.
* - `immediate`: the data is committed as soon as it is loaded.
* - `after-load`: the data is committed after all non-lazy loaders have finished loading.
*/
type DefineDataLoaderCommit = 'immediate' | 'after-load';
interface DataLoaderContextBase {
/**
* Signal associated with the current navigation. It is aborted when the navigation is canceled or an error occurs.
*/
signal: AbortSignal | undefined;
}
/**
* Data Loader composable returned by `defineLoader()`.
* @see {@link DefineDataLoader}
*/
interface UseDataLoader<Data = unknown, TError = unknown> {
[IS_USE_DATA_LOADER_KEY]: true;
/**
* Data Loader composable returned by `defineLoader()`.
*
* @example
* Returns the Data loader data, isLoading, error etc. Meant to be used in `setup()` or `<script setup>` **without `await`**:
* ```vue
* <script setup>
* const { data, isLoading, error } = useUserData()
* </script>
* ```
*
* @example
* It also returns a promise of the data when used in nested loaders. Note this `data` is **not a ref**. This is not meant to be used in `setup()` or `<script setup>`.
* ```ts
* export const useUserConnections = defineLoader(async () => {
* const user = await useUserData()
* return fetchUserConnections(user.id)
* })
* ```
*/
(): _PromiseMerged<Exclude<Data, NavigationResult | undefined>, UseDataLoaderResult<Exclude<Data, NavigationResult>, TError>>;
/**
* Internals of the data loader.
* @internal
*/
_: UseDataLoaderInternals<Exclude<Data, NavigationResult | undefined>, TError>;
}
/**
* Internal properties of a data loader composable. Used by the internal implementation of `defineLoader()`. **Should
* not be used in application code.**
*/
interface UseDataLoaderInternals<Data = unknown, TError = unknown> {
/**
* Loads the data from the cache if possible, otherwise loads it from the loader and awaits it.
*
* @param to - route location to load the data for
* @param router - router instance
* @param from - route location we are coming from
* @param parent - parent data loader entry
*/
load: (to: RouteLocationNormalizedLoaded, router: Router, from?: RouteLocationNormalizedLoaded, parent?: DataLoaderEntryBase) => Promise<void>;
/**
* Resolved options for the loader.
*/
options: DefineDataLoaderOptionsBase_LaxData;
/**
* Gets the entry associated with the router instance. Assumes the data loader has been loaded and that the entry
* exists.
*
* @param router - router instance
*/
getEntry(router: Router): DataLoaderEntryBase<Data, TError>;
}
/**
* Return value of a loader composable defined with `defineLoader()`.
*/
interface UseDataLoaderResult<TData = unknown, TError = ErrorDefault> {
/**
* Data returned by the loader. If the data loader is lazy, it will be undefined until the first load.
*/
data: ShallowRef<TData>;
/**
* Whether there is an ongoing request.
*/
isLoading: ShallowRef<boolean>;
/**
* Error if there was an error.
*/
error: ShallowRef<TError | null>;
/**
* Reload the data using the current route location. Returns a promise that resolves when the data is reloaded. This
* method should not be called during a navigation as it can conflict with an ongoing load and lead to
* inconsistencies.
*/
reload(): Promise<void>;
/**
* Reload the data using the route location passed as argument. Returns a promise that resolves when the data is reloaded.
*
* @param route - route location to load the data for
*/
reload(route: RouteLocationNormalizedLoaded): Promise<void>;
}
/**
* Loader function that can be passed to `defineLoader()`.
*/
interface DefineLoaderFn<Data, Context extends DataLoaderContextBase = DataLoaderContextBase, Route = RouteLocationNormalizedLoaded> {
(route: Route, context: Context): Promise<Data>;
}
//#endregion
export { _PromiseMerged as _, DefineLoaderFn as a, trackRoute as b, UseDataLoaderResult as c, DataLoaderPlugin as d, DataLoaderPluginOptions as f, useIsDataLoading as g, reroute as h, DefineDataLoaderOptionsBase_LaxData as i, toLazyValue as l, SetupLoaderGuardOptions as m, DataLoaderEntryBase as n, UseDataLoader as o, NavigationResult as p, DefineDataLoaderOptionsBase_DefinedData as r, UseDataLoaderInternals as s, DataLoaderContextBase as t, ErrorDefault as u, getCurrentContext as v, withLoaderContext as x, setCurrentContext as y };
+322
View File
@@ -0,0 +1,322 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { d as isNavigationFailure, l as NavigationFailureType } from "./useApi-DtucMc-S.js";
import { effectScope, inject, shallowRef } from "vue";
//#region src/experimental/data-loaders/createDataLoader.ts
const toLazyValue = (lazy, to, from) => typeof lazy === "function" ? lazy(to, from) : lazy;
//#endregion
//#region src/experimental/data-loaders/symbols.ts
/**
* Retrieves the internal version of loaders.
* @internal
*/
const LOADER_SET_KEY = Symbol("loaders");
/**
* Retrieves the internal version of loader entries.
* @internal
*/
const LOADER_ENTRIES_KEY = Symbol("loaderEntries");
/**
* Added to the loaders returned by `defineLoader()` to identify them.
* Allows to extract exported useData() from a component.
* @internal
*/
const IS_USE_DATA_LOADER_KEY = Symbol();
/**
* Symbol used to save the pending location on the router.
* @internal
*/
const PENDING_LOCATION_KEY = Symbol();
/**
* Symbol used to know there is no value staged for the loader and that commit should be skipped.
* @internal
*/
const STAGED_NO_VALUE = Symbol();
/**
* Gives access to the current app and it's `runWithContext` method.
* @internal
*/
const APP_KEY = Symbol();
/**
* Gives access to an AbortController that aborts when the navigation is canceled.
* @internal
*/
const ABORT_CONTROLLER_KEY = Symbol();
/**
* Symbol used to save the initial data on the router.
* @internal
*/
const IS_SSR_KEY = Symbol();
/**
* Symbol used to get the effect scope used for data loaders.
* @internal
*/
const DATA_LOADERS_EFFECT_SCOPE_KEY = Symbol();
//#endregion
//#region src/experimental/data-loaders/utils.ts
/**
* Check if a value is a `DataLoader`.
*
* @param loader - the object to check
*/
function isDataLoader(loader) {
return loader && loader[IS_USE_DATA_LOADER_KEY];
}
/**
* @internal: data loaders authoring only. Use `getCurrentContext` instead.
*/
let currentContext;
function getCurrentContext() {
return currentContext || [];
}
/**
* Sets the current context for data loaders. This allows for nested loaders to be aware of their parent context.
* INTERNAL ONLY.
*
* @param context - the context to set
* @internal
*/
function setCurrentContext(context) {
currentContext = context ? context.length ? context : null : null;
}
/**
* Restore the current context after a promise is resolved.
* @param promise - promise to wrap
*/
function withLoaderContext(promise) {
const context = currentContext;
return promise.finally(() => currentContext = context);
}
const assign = Object.assign;
/**
* Track the reads of a route and its properties
* @internal
* @param route - route to track
*/
function trackRoute(route) {
const [params, paramReads] = trackObjectReads(route.params);
const [query, queryReads] = trackObjectReads(route.query);
let hash = { v: null };
return [
{
...route,
get hash() {
return hash.v = route.hash;
},
params,
query
},
paramReads,
queryReads,
hash
];
}
/**
* Track the reads of an object (that doesn't change) and add the read properties to an object
* @internal
* @param obj - object to track
*/
function trackObjectReads(obj) {
const reads = {};
return [new Proxy(obj, { get(target, p, receiver) {
const value = Reflect.get(target, p, receiver);
reads[p] = value;
return value;
} }), reads];
}
/**
* Returns `true` if `inner` is a subset of `outer`. Used to check if a tr
*
* @internal
* @param outer - the bigger params
* @param inner - the smaller params
*/
function isSubsetOf(inner, outer) {
for (const key in inner) {
const innerValue = inner[key];
const outerValue = outer[key];
if (typeof innerValue === "string") {
if (innerValue !== outerValue) return false;
} else if (!innerValue || !outerValue) {
if (innerValue !== outerValue) return false;
} else if (!Array.isArray(outerValue) || outerValue.length !== innerValue.length || innerValue.some((value, i) => value !== outerValue[i])) return false;
}
return true;
}
//#endregion
//#region src/experimental/data-loaders/navigation-guard.ts
/**
* Key to inject the global loading state for loaders used in `useIsDataLoading`.
* @internal
*/
const IS_DATA_LOADING_KEY = Symbol();
/**
* TODO: export functions that allow preloading outside of a navigation guard
*/
/**
* Setups the different Navigation Guards to collect the data loaders from the route records and then to execute them.
* @internal used by the `DataLoaderPlugin`
* @see {@link DataLoaderPlugin}
*
* @param router - the router instance
* @returns
*/
function setupLoaderGuard({ router, app, effect: scope, isSSR, errors: globalErrors = [] }) {
if (router[LOADER_ENTRIES_KEY] != null) {
if (process.env.NODE_ENV !== "production") console.warn("[vue-router]: Data Loader was setup twice. Make sure to setup only once.");
return () => {};
}
if (process.env.NODE_ENV === "development" && !isSSR) console.warn("[vue-router]: Data Loader is experimental and subject to breaking changes in the future.");
router[LOADER_ENTRIES_KEY] = /* @__PURE__ */ new WeakMap();
router[APP_KEY] = app;
router[DATA_LOADERS_EFFECT_SCOPE_KEY] = scope;
router[IS_SSR_KEY] = !!isSSR;
const isDataLoading = scope.run(() => shallowRef(false));
app.provide(IS_DATA_LOADING_KEY, isDataLoading);
const removeLoaderGuard = router.beforeEach((to) => {
if (router[PENDING_LOCATION_KEY]) router[PENDING_LOCATION_KEY].meta[ABORT_CONTROLLER_KEY]?.abort();
router[PENDING_LOCATION_KEY] = to;
to.meta[LOADER_SET_KEY] = /* @__PURE__ */ new Set();
to.meta[ABORT_CONTROLLER_KEY] = new AbortController();
for (const record of to.matched) record.meta[LOADER_SET_KEY] ??= new Set(record.meta.loaders || []);
});
const removeDataLoaderGuard = router.beforeResolve((to, from) => {
for (const record of to.matched) {
for (const loader of record.meta[LOADER_SET_KEY]) to.meta[LOADER_SET_KEY].add(loader);
for (const componentName in record.mods) {
const viewModule = record.mods[componentName];
for (const exportName in viewModule) {
const exportValue = viewModule[exportName];
if (isDataLoader(exportValue)) to.meta[LOADER_SET_KEY].add(exportValue);
}
const component = record.components?.[componentName];
if (component && Array.isArray(component.__loaders)) {
for (const loader of component.__loaders) if (isDataLoader(loader)) to.meta[LOADER_SET_KEY].add(loader);
}
}
}
const loaders = Array.from(to.meta[LOADER_SET_KEY]);
const { signal } = to.meta[ABORT_CONTROLLER_KEY];
setCurrentContext([]);
isDataLoading.value = true;
return Promise.all(loaders.map((loader) => {
const { server, lazy, errors } = loader._.options;
if (!server && isSSR) return;
const ret = scope.run(() => app.runWithContext(() => loader._.load(to, router, from)));
return !isSSR && toLazyValue(lazy, to, from) ? void 0 : ret.catch((reason) => {
if (errors === true) {
if (Array.isArray(globalErrors) ? globalErrors.some((Err) => reason instanceof Err) : globalErrors(reason)) return;
} else if (errors && (Array.isArray(errors) ? errors.some((Err) => reason instanceof Err) : errors(reason))) return;
throw reason;
});
})).then((results) => {
if (process.env.NODE_ENV !== "production") {
for (const result of results) if (result instanceof NavigationResult) {
console.warn("[vue-router]: Returning a NavigationResult from a loader is deprecated. Use reroute() instead, which throws internally.");
throw result;
}
}
}).catch((error) => error instanceof NavigationResult ? error.value : signal.aborted && error === signal.reason ? false : Promise.reject(error)).finally(() => {
setCurrentContext([]);
isDataLoading.value = false;
});
});
const removeAfterEach = router.afterEach((to, from, failure) => {
if (failure) {
to.meta[ABORT_CONTROLLER_KEY]?.abort(failure);
if (isNavigationFailure(failure, NavigationFailureType.duplicated)) for (const loader of to.meta[LOADER_SET_KEY]) loader._.getEntry(router).resetPending();
} else for (const loader of to.meta[LOADER_SET_KEY]) {
const { commit, lazy } = loader._.options;
if (commit === "after-load") {
const entry = loader._.getEntry(router);
if (entry && (!toLazyValue(lazy, to, from) || !entry.isLoading.value)) entry.commit(to);
}
}
if (router[PENDING_LOCATION_KEY] === to) router[PENDING_LOCATION_KEY] = null;
});
const removeOnError = router.onError((error, to) => {
to.meta[ABORT_CONTROLLER_KEY]?.abort(error);
if (router[PENDING_LOCATION_KEY] === to) router[PENDING_LOCATION_KEY] = null;
});
return () => {
delete router[LOADER_ENTRIES_KEY];
delete router[APP_KEY];
removeLoaderGuard();
removeDataLoaderGuard();
removeAfterEach();
removeOnError();
};
}
/**
* Allows data loaders to change navigation. Called by {@link reroute}.
*
* @internal
*/
var NavigationResult = class {
constructor(value) {
this.value = value;
}
};
/**
* Changes the navigation from within a data loader. Accepts the same values as a navigation
* guard return: a route location to redirect to, or `false` to cancel the navigation.
*
* @example
* ```ts
* export const useUserData = defineBasicLoader(async (to) => {
* const user = await fetchUser(to.params.id)
* if (!user) {
* reroute('/404')
* }
* return user
* })
* ```
*/
function reroute(to) {
throw new NavigationResult(to);
}
/**
* Data Loader plugin to add data loading support to Vue Router.
*
* @example
* ```ts
* const router = createRouter({
* routes,
* history: createWebHistory(),
* })
*
* const app = createApp({})
* app.use(DataLoaderPlugin, { router })
* app.use(router)
* ```
*/
function DataLoaderPlugin(app, options) {
const effect = effectScope(true);
const removeGuards = setupLoaderGuard(assign({
app,
effect
}, options));
const { unmount } = app;
app.unmount = () => {
effect.stop();
removeGuards();
unmount.call(app);
};
}
/**
* Return a ref that reflects the global loading state of all loaders within a navigation.
* This state doesn't update if `refresh()` is manually called.
*/
function useIsDataLoading() {
return inject(IS_DATA_LOADING_KEY);
}
//#endregion
export { LOADER_SET_KEY as _, assign as a, toLazyValue as b, setCurrentContext as c, ABORT_CONTROLLER_KEY as d, APP_KEY as f, LOADER_ENTRIES_KEY as g, IS_USE_DATA_LOADER_KEY as h, useIsDataLoading as i, trackRoute as l, IS_SSR_KEY as m, NavigationResult as n, getCurrentContext as o, DATA_LOADERS_EFFECT_SCOPE_KEY as p, reroute as r, isSubsetOf as s, DataLoaderPlugin as t, withLoaderContext as u, PENDING_LOCATION_KEY as v, STAGED_NO_VALUE as y };
File diff suppressed because it is too large Load Diff
+488
View File
@@ -0,0 +1,488 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
const require_unplugin = require('./unplugin-DL8B31Qb.cjs');
let scule = require("scule");
let pathe = require("pathe");
let local_pkg = require("local-pkg");
//#region src/unplugin/utils/index.ts
const ts = String.raw;
/**
* Pads a single-line string with spaces.
*
* @internal
*
* @param spaces The number of spaces to pad with.
* @param str The string to pad, none if omitted.
* @returns The padded string.
*/
function pad(spaces, str = "") {
return " ".repeat(spaces) + str;
}
/**
* Formats an array of union items as a multiline union type.
*
* @internal
*
* @param items The items to format.
* @param spaces The number of spaces to indent each line.
* @returns The formatted multiline union type.
*/
function formatMultilineUnion(items, spaces) {
return (items.length ? items : ["never"]).map((s) => `| ${s}`).join(`\n${pad(spaces)}`);
}
/**
* Converts a string value to a string literal, escaping as necessary.
*
* @internal
*
* @param str the string to convert to a string type
* @returns The string wrapped in single quotes and escaped.
* @example
* toStringLiteral('hello') // returns "'hello'"
* toStringLiteral("it's fine") // returns "'it\'s fine'"
*/
function toStringLiteral(str) {
return `'${str.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
}
//#endregion
//#region src/unplugin/core/utils.ts
function warn(msg, type = "warn") {
console[type](`⚠️ [vue-router]: ${msg}`);
}
function logTree(tree, log) {
log(printTree(tree));
}
const MAX_LEVEL = 1e3;
function printTree(tree, level = 0, parentPre = "", treeStr = "") {
if (typeof tree !== "object" || level >= MAX_LEVEL) return "";
if (tree instanceof Map) {
const total = tree.size;
let index = 0;
for (const [_key, child] of tree) {
const hasNext = index++ < total - 1;
const { children } = child;
treeStr += `${`${parentPre}${hasNext ? "├" : "└"}${"─" + (children.size > 0 ? "┬" : "")} `}${child}\n`;
if (children) treeStr += printTree(children, level + 1, `${parentPre}${hasNext ? "│" : " "} `);
}
} else {
const children = tree.children;
treeStr = `${tree}\n`;
if (children) treeStr += printTree(children, level + 1);
}
return treeStr;
}
/**
* Type safe alternative to Array.isArray
* https://github.com/microsoft/TypeScript/pull/48228
*/
const isArray = Array.isArray;
function trimExtension(path, extensions) {
for (const extension of extensions) {
const lastDot = path.endsWith(extension) ? -extension.length : 0;
if (lastDot < 0) return path.slice(0, lastDot);
}
return path;
}
function throttle(fn, wait, initialWait) {
let pendingExecutionTimeout = null;
let pendingExecution = false;
let executionTimeout = null;
return () => {
if (pendingExecutionTimeout == null) {
pendingExecutionTimeout = setTimeout(() => {
pendingExecutionTimeout = null;
if (pendingExecution) {
pendingExecution = false;
fn();
}
}, wait);
executionTimeout = setTimeout(() => {
executionTimeout = null;
fn();
}, initialWait);
} else if (executionTimeout == null) pendingExecution = true;
};
}
const LEADING_SLASH_RE = /^\//;
const TRAILING_SLASH_RE = /\/$/;
const ESCAPED_TRAILING_SLASH_RE = /\\\/$/;
function joinPath(...paths) {
let result = "";
for (const path of paths) result = result.replace(TRAILING_SLASH_RE, "") + (path && "/" + path.replace(LEADING_SLASH_RE, ""));
return result || "/";
}
function paramToName({ paramName, modifier, isSplat }) {
return `${isSplat ? "$" : ""}${paramName.charAt(0).toUpperCase() + paramName.slice(1)}${modifier}`;
}
/**
* Creates a name based of the node path segments.
*
* @param node - the node to get the path from
* @param parent - the parent node
* @returns a route name
*/
function getPascalCaseRouteName(node) {
if (node.parent?.isRoot() && node.value.pathSegment === "") return "Root";
let name = node.value.subSegments.map((segment) => {
if (typeof segment === "string") return (0, scule.pascalCase)(segment);
return paramToName(segment);
}).join("");
if (node.value.components.size && node.children.has("index")) name += "Parent";
const parent = node.parent;
return (parent && !parent.isRoot() ? getPascalCaseRouteName(parent).replace(/Parent$/, "") : "") + name;
}
/**
* Joins the path segments of a node into a name that corresponds to the filepath represented by the node.
*
* @param node - the node to get the path from
* @returns a route name
*/
function getFileBasedRouteName(node) {
if (!node.parent) return "";
return getFileBasedRouteName(node.parent) + "/" + (node.value.rawSegment === "index" ? "" : node.value.rawSegment);
}
function mergeRouteRecordOverride(a, b) {
const merged = {};
const keys = [...new Set([...Object.keys(a), ...Object.keys(b)])];
for (const key of keys) if (key === "alias") merged[key] = [].concat(a.alias || [], b.alias || []);
else if (key === "meta") merged[key] = mergeDeep(a[key] || {}, b[key] || {});
else if (key === "params") merged[key] = {
path: {
...a[key]?.path,
...b[key]?.path
},
query: {
...a[key]?.query,
...b[key]?.query
}
};
else merged[key] = b[key] ?? a[key];
return merged;
}
function isObject(obj) {
return obj && typeof obj === "object";
}
function mergeDeep(...objects) {
return objects.reduce((prev, obj) => {
Object.keys(obj).forEach((key) => {
const pVal = prev[key];
const oVal = obj[key];
if (Array.isArray(pVal) && Array.isArray(oVal)) prev[key] = pVal.concat(...oVal);
else if (isObject(pVal) && isObject(oVal)) prev[key] = mergeDeep(pVal, oVal);
else prev[key] = oVal;
});
return prev;
}, {});
}
/**
* Returns a route path to be used by the router with any defined prefix from an absolute path to a file. Since it
* returns a route path, it will remove the extension from the file.
*
* @param options - RoutesFolderOption to apply
* @param filePath - absolute path to file
* @returns a route path to be used by the router with any defined prefix
*/
function asRoutePath({ src, path = "", extensions }, filePath) {
return trimExtension(typeof path === "string" ? path + filePath.slice(src.length + 1) : path(filePath), extensions);
}
function appendExtensionListToPattern(filePatterns, extensions) {
const extensionPattern = extensions.length === 1 ? extensions[0] : `.{${extensions.map((extension) => extension.replace(".", "")).join(",")}}`;
return Array.isArray(filePatterns) ? filePatterns.map((filePattern) => `${filePattern}${extensionPattern}`) : `${filePatterns}${extensionPattern}`;
}
var ImportsMap = class {
map = /* @__PURE__ */ new Map();
constructor() {}
add(path, importEntry) {
if (!this.map.has(path)) this.map.set(path, /* @__PURE__ */ new Map());
const imports = this.map.get(path);
if (typeof importEntry === "string") imports.set(importEntry, importEntry);
else imports.set(importEntry.as || importEntry.name, importEntry.name);
return this;
}
/**
* Check if the given path has the given import name.
*
* @param path - the path to check
* @param name - the import name to check
*/
has(path, name) {
return this.map.has(path) && this.map.get(path).has(name);
}
/**
* Add a default import. Alias for `add(path, { name: 'default', as })`.
*
* @param path - the path to import from
* @param as - the name to import as
*/
addDefault(path, as) {
return this.add(path, {
name: "default",
as
});
}
/**
* Get the list of imports for the given path.
*
* @param path - the path to get the import list for
* @returns the list of imports for the given path
*/
getImportList(path) {
if (!this.map.has(path)) return [];
return Array.from(this.map.get(path)).map(([as, name]) => ({
as: as || name,
name
}));
}
toString() {
let importStatements = "";
for (const [path, imports] of this.map) {
if (!imports.size) continue;
const fromImportPath = toStringLiteral(path);
if (imports.size === 1) {
const [[importName, maybeDefault]] = [...imports.entries()];
if (maybeDefault === "default") {
importStatements += `import ${importName} from ${fromImportPath}\n`;
continue;
}
}
importStatements += `import { ${Array.from(imports).map(([as, name]) => as === name ? name : `${name} as ${as}`).join(", ")} } from ${fromImportPath}\n`;
}
return importStatements;
}
get size() {
return this.map.size;
}
};
//#endregion
//#region src/unplugin/options.ts
/**
* Resolves an overridable option by calling the function with the existing
* value if it's a function, otherwise returning the passed `value`. If `value`
* is undefined, it returns the `defaultValue` instead.
*
* @param defaultValue default value for the option
* @param value and overridable option
*
* @internal
*/
function resolveOverridableOption(defaultValue, value) {
return typeof value === "function" ? value(defaultValue) : value ?? defaultValue;
}
/**
* Default options for experimental param parsers.
*/
const DEFAULT_PARAM_PARSERS_OPTIONS = { dir: ["src/params"] };
/**
* Default plugin options.
*/
const DEFAULT_OPTIONS = {
extensions: [".vue"],
exclude: [],
routesFolder: "src/pages",
filePatterns: ["**/*"],
routeBlockLang: "json5",
getRouteName: getFileBasedRouteName,
importMode: "async",
root: process.cwd(),
dts: (0, local_pkg.isPackageExists)("typescript"),
logs: false,
_inspect: false,
pathParser: { dotNesting: true },
watch: !process.env.CI,
experimental: {}
};
function normalizeRoutesFolderOption(routesFolder) {
return (isArray(routesFolder) ? routesFolder : [routesFolder]).map((routeOption) => normalizeRouteOption(typeof routeOption === "string" ? { src: routeOption } : routeOption));
}
function normalizeRouteOption(routeOption) {
return {
...routeOption,
filePatterns: routeOption.filePatterns ? typeof routeOption.filePatterns === "function" ? routeOption.filePatterns : isArray(routeOption.filePatterns) ? routeOption.filePatterns : [routeOption.filePatterns] : void 0,
exclude: routeOption.exclude ? typeof routeOption.exclude === "function" ? routeOption.exclude : isArray(routeOption.exclude) ? routeOption.exclude : [routeOption.exclude] : void 0
};
}
/**
* Normalize user options with defaults and resolved paths.
*
* @param options - user provided options
* @returns normalized options
*/
function resolveOptions(options) {
const root = options.root || DEFAULT_OPTIONS.root;
const routesFolder = normalizeRoutesFolderOption(options.routesFolder || DEFAULT_OPTIONS.routesFolder).map((routeOption) => ({
...routeOption,
src: (0, pathe.resolve)(root, routeOption.src)
}));
const paramParsers = options.experimental?.paramParsers ? options.experimental.paramParsers === true ? DEFAULT_PARAM_PARSERS_OPTIONS : {
...DEFAULT_PARAM_PARSERS_OPTIONS,
...options.experimental.paramParsers
} : void 0;
const paramParsersDir = (paramParsers?.dir ? isArray(paramParsers.dir) ? paramParsers.dir : [paramParsers.dir] : []).map((dir) => (0, pathe.resolve)(root, dir));
const autoExportsDataLoaders = options.experimental?.autoExportsDataLoaders ? (isArray(options.experimental.autoExportsDataLoaders) ? options.experimental.autoExportsDataLoaders : [options.experimental.autoExportsDataLoaders]).map((path) => (0, pathe.resolve)(root, path)) : void 0;
const experimental = {
...options.experimental,
autoExportsDataLoaders,
paramParsers: paramParsers && {
...paramParsers,
dir: paramParsersDir
}
};
if (options.extensions) options.extensions = options.extensions.map((ext) => {
if (!ext.startsWith(".")) {
warn(`Invalid extension "${ext}". Extensions must start with a dot.`);
return "." + ext;
}
return ext;
}).sort((a, b) => b.length - a.length);
const filePatterns = options.filePatterns ? isArray(options.filePatterns) ? options.filePatterns : [options.filePatterns] : DEFAULT_OPTIONS.filePatterns;
const exclude = options.exclude ? isArray(options.exclude) ? options.exclude : [options.exclude] : DEFAULT_OPTIONS.exclude;
return {
...DEFAULT_OPTIONS,
...options,
experimental,
routesFolder,
filePatterns,
exclude
};
}
/**
* Merge all the possible extensions as an array of unique values
* @param options - user provided options
* @internal
*/
function mergeAllExtensions(options) {
const allExtensions = new Set(options.extensions);
for (const routeOption of options.routesFolder) if (routeOption.extensions) {
const extensions = resolveOverridableOption(options.extensions, routeOption.extensions);
for (const ext of extensions) allExtensions.add(ext);
}
return Array.from(allExtensions.values());
}
//#endregion
Object.defineProperty(exports, 'DEFAULT_OPTIONS', {
enumerable: true,
get: function () {
return DEFAULT_OPTIONS;
}
});
Object.defineProperty(exports, 'DEFAULT_PARAM_PARSERS_OPTIONS', {
enumerable: true,
get: function () {
return DEFAULT_PARAM_PARSERS_OPTIONS;
}
});
Object.defineProperty(exports, 'ESCAPED_TRAILING_SLASH_RE', {
enumerable: true,
get: function () {
return ESCAPED_TRAILING_SLASH_RE;
}
});
Object.defineProperty(exports, 'ImportsMap', {
enumerable: true,
get: function () {
return ImportsMap;
}
});
Object.defineProperty(exports, 'appendExtensionListToPattern', {
enumerable: true,
get: function () {
return appendExtensionListToPattern;
}
});
Object.defineProperty(exports, 'asRoutePath', {
enumerable: true,
get: function () {
return asRoutePath;
}
});
Object.defineProperty(exports, 'formatMultilineUnion', {
enumerable: true,
get: function () {
return formatMultilineUnion;
}
});
Object.defineProperty(exports, 'getFileBasedRouteName', {
enumerable: true,
get: function () {
return getFileBasedRouteName;
}
});
Object.defineProperty(exports, 'getPascalCaseRouteName', {
enumerable: true,
get: function () {
return getPascalCaseRouteName;
}
});
Object.defineProperty(exports, 'joinPath', {
enumerable: true,
get: function () {
return joinPath;
}
});
Object.defineProperty(exports, 'logTree', {
enumerable: true,
get: function () {
return logTree;
}
});
Object.defineProperty(exports, 'mergeAllExtensions', {
enumerable: true,
get: function () {
return mergeAllExtensions;
}
});
Object.defineProperty(exports, 'mergeRouteRecordOverride', {
enumerable: true,
get: function () {
return mergeRouteRecordOverride;
}
});
Object.defineProperty(exports, 'pad', {
enumerable: true,
get: function () {
return pad;
}
});
Object.defineProperty(exports, 'resolveOptions', {
enumerable: true,
get: function () {
return resolveOptions;
}
});
Object.defineProperty(exports, 'resolveOverridableOption', {
enumerable: true,
get: function () {
return resolveOverridableOption;
}
});
Object.defineProperty(exports, 'throttle', {
enumerable: true,
get: function () {
return throttle;
}
});
Object.defineProperty(exports, 'toStringLiteral', {
enumerable: true,
get: function () {
return toStringLiteral;
}
});
Object.defineProperty(exports, 'ts', {
enumerable: true,
get: function () {
return ts;
}
});
Object.defineProperty(exports, 'warn', {
enumerable: true,
get: function () {
return warn;
}
});
+368
View File
@@ -0,0 +1,368 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { pascalCase } from "scule";
import { resolve } from "pathe";
import { isPackageExists } from "local-pkg";
//#region src/unplugin/utils/index.ts
const ts = String.raw;
/**
* Pads a single-line string with spaces.
*
* @internal
*
* @param spaces The number of spaces to pad with.
* @param str The string to pad, none if omitted.
* @returns The padded string.
*/
function pad(spaces, str = "") {
return " ".repeat(spaces) + str;
}
/**
* Formats an array of union items as a multiline union type.
*
* @internal
*
* @param items The items to format.
* @param spaces The number of spaces to indent each line.
* @returns The formatted multiline union type.
*/
function formatMultilineUnion(items, spaces) {
return (items.length ? items : ["never"]).map((s) => `| ${s}`).join(`\n${pad(spaces)}`);
}
/**
* Converts a string value to a string literal, escaping as necessary.
*
* @internal
*
* @param str the string to convert to a string type
* @returns The string wrapped in single quotes and escaped.
* @example
* toStringLiteral('hello') // returns "'hello'"
* toStringLiteral("it's fine") // returns "'it\'s fine'"
*/
function toStringLiteral(str) {
return `'${str.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
}
//#endregion
//#region src/unplugin/core/utils.ts
function warn(msg, type = "warn") {
console[type](`⚠️ [vue-router]: ${msg}`);
}
function logTree(tree, log) {
log(printTree(tree));
}
const MAX_LEVEL = 1e3;
function printTree(tree, level = 0, parentPre = "", treeStr = "") {
if (typeof tree !== "object" || level >= MAX_LEVEL) return "";
if (tree instanceof Map) {
const total = tree.size;
let index = 0;
for (const [_key, child] of tree) {
const hasNext = index++ < total - 1;
const { children } = child;
treeStr += `${`${parentPre}${hasNext ? "├" : "└"}${"─" + (children.size > 0 ? "┬" : "")} `}${child}\n`;
if (children) treeStr += printTree(children, level + 1, `${parentPre}${hasNext ? "│" : " "} `);
}
} else {
const children = tree.children;
treeStr = `${tree}\n`;
if (children) treeStr += printTree(children, level + 1);
}
return treeStr;
}
/**
* Type safe alternative to Array.isArray
* https://github.com/microsoft/TypeScript/pull/48228
*/
const isArray = Array.isArray;
function trimExtension(path, extensions) {
for (const extension of extensions) {
const lastDot = path.endsWith(extension) ? -extension.length : 0;
if (lastDot < 0) return path.slice(0, lastDot);
}
return path;
}
function throttle(fn, wait, initialWait) {
let pendingExecutionTimeout = null;
let pendingExecution = false;
let executionTimeout = null;
return () => {
if (pendingExecutionTimeout == null) {
pendingExecutionTimeout = setTimeout(() => {
pendingExecutionTimeout = null;
if (pendingExecution) {
pendingExecution = false;
fn();
}
}, wait);
executionTimeout = setTimeout(() => {
executionTimeout = null;
fn();
}, initialWait);
} else if (executionTimeout == null) pendingExecution = true;
};
}
const LEADING_SLASH_RE = /^\//;
const TRAILING_SLASH_RE = /\/$/;
const ESCAPED_TRAILING_SLASH_RE = /\\\/$/;
function joinPath(...paths) {
let result = "";
for (const path of paths) result = result.replace(TRAILING_SLASH_RE, "") + (path && "/" + path.replace(LEADING_SLASH_RE, ""));
return result || "/";
}
function paramToName({ paramName, modifier, isSplat }) {
return `${isSplat ? "$" : ""}${paramName.charAt(0).toUpperCase() + paramName.slice(1)}${modifier}`;
}
/**
* Creates a name based of the node path segments.
*
* @param node - the node to get the path from
* @param parent - the parent node
* @returns a route name
*/
function getPascalCaseRouteName(node) {
if (node.parent?.isRoot() && node.value.pathSegment === "") return "Root";
let name = node.value.subSegments.map((segment) => {
if (typeof segment === "string") return pascalCase(segment);
return paramToName(segment);
}).join("");
if (node.value.components.size && node.children.has("index")) name += "Parent";
const parent = node.parent;
return (parent && !parent.isRoot() ? getPascalCaseRouteName(parent).replace(/Parent$/, "") : "") + name;
}
/**
* Joins the path segments of a node into a name that corresponds to the filepath represented by the node.
*
* @param node - the node to get the path from
* @returns a route name
*/
function getFileBasedRouteName(node) {
if (!node.parent) return "";
return getFileBasedRouteName(node.parent) + "/" + (node.value.rawSegment === "index" ? "" : node.value.rawSegment);
}
function mergeRouteRecordOverride(a, b) {
const merged = {};
const keys = [...new Set([...Object.keys(a), ...Object.keys(b)])];
for (const key of keys) if (key === "alias") merged[key] = [].concat(a.alias || [], b.alias || []);
else if (key === "meta") merged[key] = mergeDeep(a[key] || {}, b[key] || {});
else if (key === "params") merged[key] = {
path: {
...a[key]?.path,
...b[key]?.path
},
query: {
...a[key]?.query,
...b[key]?.query
}
};
else merged[key] = b[key] ?? a[key];
return merged;
}
function isObject(obj) {
return obj && typeof obj === "object";
}
function mergeDeep(...objects) {
return objects.reduce((prev, obj) => {
Object.keys(obj).forEach((key) => {
const pVal = prev[key];
const oVal = obj[key];
if (Array.isArray(pVal) && Array.isArray(oVal)) prev[key] = pVal.concat(...oVal);
else if (isObject(pVal) && isObject(oVal)) prev[key] = mergeDeep(pVal, oVal);
else prev[key] = oVal;
});
return prev;
}, {});
}
/**
* Returns a route path to be used by the router with any defined prefix from an absolute path to a file. Since it
* returns a route path, it will remove the extension from the file.
*
* @param options - RoutesFolderOption to apply
* @param filePath - absolute path to file
* @returns a route path to be used by the router with any defined prefix
*/
function asRoutePath({ src, path = "", extensions }, filePath) {
return trimExtension(typeof path === "string" ? path + filePath.slice(src.length + 1) : path(filePath), extensions);
}
function appendExtensionListToPattern(filePatterns, extensions) {
const extensionPattern = extensions.length === 1 ? extensions[0] : `.{${extensions.map((extension) => extension.replace(".", "")).join(",")}}`;
return Array.isArray(filePatterns) ? filePatterns.map((filePattern) => `${filePattern}${extensionPattern}`) : `${filePatterns}${extensionPattern}`;
}
var ImportsMap = class {
map = /* @__PURE__ */ new Map();
constructor() {}
add(path, importEntry) {
if (!this.map.has(path)) this.map.set(path, /* @__PURE__ */ new Map());
const imports = this.map.get(path);
if (typeof importEntry === "string") imports.set(importEntry, importEntry);
else imports.set(importEntry.as || importEntry.name, importEntry.name);
return this;
}
/**
* Check if the given path has the given import name.
*
* @param path - the path to check
* @param name - the import name to check
*/
has(path, name) {
return this.map.has(path) && this.map.get(path).has(name);
}
/**
* Add a default import. Alias for `add(path, { name: 'default', as })`.
*
* @param path - the path to import from
* @param as - the name to import as
*/
addDefault(path, as) {
return this.add(path, {
name: "default",
as
});
}
/**
* Get the list of imports for the given path.
*
* @param path - the path to get the import list for
* @returns the list of imports for the given path
*/
getImportList(path) {
if (!this.map.has(path)) return [];
return Array.from(this.map.get(path)).map(([as, name]) => ({
as: as || name,
name
}));
}
toString() {
let importStatements = "";
for (const [path, imports] of this.map) {
if (!imports.size) continue;
const fromImportPath = toStringLiteral(path);
if (imports.size === 1) {
const [[importName, maybeDefault]] = [...imports.entries()];
if (maybeDefault === "default") {
importStatements += `import ${importName} from ${fromImportPath}\n`;
continue;
}
}
importStatements += `import { ${Array.from(imports).map(([as, name]) => as === name ? name : `${name} as ${as}`).join(", ")} } from ${fromImportPath}\n`;
}
return importStatements;
}
get size() {
return this.map.size;
}
};
//#endregion
//#region src/unplugin/options.ts
/**
* Resolves an overridable option by calling the function with the existing
* value if it's a function, otherwise returning the passed `value`. If `value`
* is undefined, it returns the `defaultValue` instead.
*
* @param defaultValue default value for the option
* @param value and overridable option
*
* @internal
*/
function resolveOverridableOption(defaultValue, value) {
return typeof value === "function" ? value(defaultValue) : value ?? defaultValue;
}
/**
* Default options for experimental param parsers.
*/
const DEFAULT_PARAM_PARSERS_OPTIONS = { dir: ["src/params"] };
/**
* Default plugin options.
*/
const DEFAULT_OPTIONS = {
extensions: [".vue"],
exclude: [],
routesFolder: "src/pages",
filePatterns: ["**/*"],
routeBlockLang: "json5",
getRouteName: getFileBasedRouteName,
importMode: "async",
root: process.cwd(),
dts: isPackageExists("typescript"),
logs: false,
_inspect: false,
pathParser: { dotNesting: true },
watch: !process.env.CI,
experimental: {}
};
function normalizeRoutesFolderOption(routesFolder) {
return (isArray(routesFolder) ? routesFolder : [routesFolder]).map((routeOption) => normalizeRouteOption(typeof routeOption === "string" ? { src: routeOption } : routeOption));
}
function normalizeRouteOption(routeOption) {
return {
...routeOption,
filePatterns: routeOption.filePatterns ? typeof routeOption.filePatterns === "function" ? routeOption.filePatterns : isArray(routeOption.filePatterns) ? routeOption.filePatterns : [routeOption.filePatterns] : void 0,
exclude: routeOption.exclude ? typeof routeOption.exclude === "function" ? routeOption.exclude : isArray(routeOption.exclude) ? routeOption.exclude : [routeOption.exclude] : void 0
};
}
/**
* Normalize user options with defaults and resolved paths.
*
* @param options - user provided options
* @returns normalized options
*/
function resolveOptions(options) {
const root = options.root || DEFAULT_OPTIONS.root;
const routesFolder = normalizeRoutesFolderOption(options.routesFolder || DEFAULT_OPTIONS.routesFolder).map((routeOption) => ({
...routeOption,
src: resolve(root, routeOption.src)
}));
const paramParsers = options.experimental?.paramParsers ? options.experimental.paramParsers === true ? DEFAULT_PARAM_PARSERS_OPTIONS : {
...DEFAULT_PARAM_PARSERS_OPTIONS,
...options.experimental.paramParsers
} : void 0;
const paramParsersDir = (paramParsers?.dir ? isArray(paramParsers.dir) ? paramParsers.dir : [paramParsers.dir] : []).map((dir) => resolve(root, dir));
const autoExportsDataLoaders = options.experimental?.autoExportsDataLoaders ? (isArray(options.experimental.autoExportsDataLoaders) ? options.experimental.autoExportsDataLoaders : [options.experimental.autoExportsDataLoaders]).map((path) => resolve(root, path)) : void 0;
const experimental = {
...options.experimental,
autoExportsDataLoaders,
paramParsers: paramParsers && {
...paramParsers,
dir: paramParsersDir
}
};
if (options.extensions) options.extensions = options.extensions.map((ext) => {
if (!ext.startsWith(".")) {
warn(`Invalid extension "${ext}". Extensions must start with a dot.`);
return "." + ext;
}
return ext;
}).sort((a, b) => b.length - a.length);
const filePatterns = options.filePatterns ? isArray(options.filePatterns) ? options.filePatterns : [options.filePatterns] : DEFAULT_OPTIONS.filePatterns;
const exclude = options.exclude ? isArray(options.exclude) ? options.exclude : [options.exclude] : DEFAULT_OPTIONS.exclude;
return {
...DEFAULT_OPTIONS,
...options,
experimental,
routesFolder,
filePatterns,
exclude
};
}
/**
* Merge all the possible extensions as an array of unique values
* @param options - user provided options
* @internal
*/
function mergeAllExtensions(options) {
const allExtensions = new Set(options.extensions);
for (const routeOption of options.routesFolder) if (routeOption.extensions) {
const extensions = resolveOverridableOption(options.extensions, routeOption.extensions);
for (const ext of extensions) allExtensions.add(ext);
}
return Array.from(allExtensions.values());
}
//#endregion
export { formatMultilineUnion as _, resolveOverridableOption as a, ts as b, appendExtensionListToPattern as c, getPascalCaseRouteName as d, joinPath as f, warn as g, throttle as h, resolveOptions as i, asRoutePath as l, mergeRouteRecordOverride as m, DEFAULT_PARAM_PARSERS_OPTIONS as n, ESCAPED_TRAILING_SLASH_RE as o, logTree as p, mergeAllExtensions as r, ImportsMap as s, DEFAULT_OPTIONS as t, getFileBasedRouteName as u, pad as v, toStringLiteral as y };
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
Object.defineProperty(exports, '__esModule', { value: true });
const require_unplugin = require('../unplugin-DL8B31Qb.cjs');
//#region src/unplugin/esbuild.ts
var esbuild_default = require_unplugin.unplugin_default.esbuild;
//#endregion
exports.default = esbuild_default;
+11
View File
@@ -0,0 +1,11 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-C8M2qFcl.cjs";
import * as esbuild0 from "esbuild";
//#region src/unplugin/esbuild.d.ts
declare const _default: (options?: Options | undefined) => esbuild0.Plugin;
export = _default;
+12
View File
@@ -0,0 +1,12 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-rGD93PHF.mjs";
import * as esbuild0 from "esbuild";
//#region src/unplugin/esbuild.d.ts
declare const _default: (options?: Options | undefined) => esbuild0.Plugin;
//#endregion
export { _default as default };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import "../options-DrVGtYpN.mjs";
import { n as unplugin_default } from "../unplugin-DuCbyUDD.mjs";
//#region src/unplugin/esbuild.ts
var esbuild_default = unplugin_default.esbuild;
//#endregion
export { esbuild_default as default };
+19
View File
@@ -0,0 +1,19 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
Object.defineProperty(exports, '__esModule', { value: true });
const require_unplugin = require('../unplugin-DL8B31Qb.cjs');
const require_options = require('../options-CDXgA1NW.cjs');
exports.AutoExportLoaders = require_unplugin.AutoExportLoaders;
exports.DEFAULT_OPTIONS = require_options.DEFAULT_OPTIONS;
exports.EditableTreeNode = require_unplugin.EditableTreeNode;
exports.VueRouterAutoImports = require_unplugin.VueRouterAutoImports;
exports.createRoutesContext = require_unplugin.createRoutesContext;
exports.createTreeNodeValue = require_unplugin.createTreeNodeValue;
exports.default = require_unplugin.unplugin_default;
exports.getFileBasedRouteName = require_options.getFileBasedRouteName;
exports.getPascalCaseRouteName = require_options.getPascalCaseRouteName;
exports.resolveOptions = require_options.resolveOptions;
+69
View File
@@ -0,0 +1,69 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { C as createTreeNodeValue, S as TreeNodeValueStatic, _ as getPascalCaseRouteName, a as ResolvedOptions, b as TreeNodeValueGroup, c as RoutesFolderOptionResolved, g as getFileBasedRouteName, h as EditableTreeNode, i as ParamParsersOptions, l as ServerContext, o as RoutesFolder, p as resolveOptions, r as Options, s as RoutesFolderOption, t as DEFAULT_OPTIONS, v as TreeNode, x as TreeNodeValueParam, y as TreeNodeValue } from "../options-C8M2qFcl.cjs";
import * as unplugin0 from "unplugin";
import { StringFilter } from "unplugin";
import { Plugin } from "vite";
//#region src/unplugin/core/context.d.ts
declare function createRoutesContext(options: ResolvedOptions): {
scanPages: (startWatchers?: boolean) => Promise<void>;
writeConfigFiles: () => void;
setServerContext: (_server: ServerContext) => void;
stopWatcher: () => void;
generateRoutes: () => string;
generateResolver: () => string;
definePageTransform(code: string, id: string): unplugin0.Thenable<unplugin0.TransformResult>;
};
//#endregion
//#region src/experimental/data-loaders/auto-exports.d.ts
/**
* {@link AutoExportLoaders} options.
*/
interface AutoExportLoadersOptions {
/**
* Filter page components to apply the auto-export. Passed to `transform.filter.id`.
*/
transformFilter: StringFilter;
/**
* Globs to match the paths of the loaders.
*/
loadersPathsGlobs: string | string[];
/**
* Root of the project. All paths are resolved relatively to this one.
* @default `process.cwd()`
*/
root?: string;
}
/**
* Vite Plugin to automatically export loaders from page components.
*
* @param options Options
* @experimental - This API is experimental and can be changed in the future. It's used internally by `experimental.autoExportsDataLoaders`
*/
declare function AutoExportLoaders({
transformFilter,
loadersPathsGlobs,
root
}: AutoExportLoadersOptions): Plugin;
//#endregion
//#region src/unplugin/index.d.ts
declare const _default: unplugin0.UnpluginInstance<Options | undefined, boolean>;
/**
* Adds useful auto imports to the AutoImport config:
* @example
* ```js
* import { VueRouterAutoImports } from 'vue-router/unplugin'
*
* AutoImport({
* imports: [VueRouterAutoImports],
* }),
* ```
*/
declare const VueRouterAutoImports: Record<string, Array<string | [importName: string, alias: string]>>;
//#endregion
export { AutoExportLoaders, type AutoExportLoadersOptions, DEFAULT_OPTIONS, EditableTreeNode, type Options, type ParamParsersOptions, type ResolvedOptions, type RoutesFolder, type RoutesFolderOption, type RoutesFolderOptionResolved, type TreeNode, type TreeNodeValue, type TreeNodeValueGroup, type TreeNodeValueParam, type TreeNodeValueStatic, VueRouterAutoImports, createRoutesContext, createTreeNodeValue, _default as default, getFileBasedRouteName, getPascalCaseRouteName, resolveOptions };
+69
View File
@@ -0,0 +1,69 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { C as createTreeNodeValue, S as TreeNodeValueStatic, _ as getPascalCaseRouteName, a as ResolvedOptions, b as TreeNodeValueGroup, c as RoutesFolderOptionResolved, g as getFileBasedRouteName, h as EditableTreeNode, i as ParamParsersOptions, l as ServerContext, o as RoutesFolder, p as resolveOptions, r as Options, s as RoutesFolderOption, t as DEFAULT_OPTIONS, v as TreeNode, x as TreeNodeValueParam, y as TreeNodeValue } from "../options-rGD93PHF.mjs";
import * as unplugin0 from "unplugin";
import { StringFilter } from "unplugin";
import { Plugin } from "vite";
//#region src/unplugin/core/context.d.ts
declare function createRoutesContext(options: ResolvedOptions): {
scanPages: (startWatchers?: boolean) => Promise<void>;
writeConfigFiles: () => void;
setServerContext: (_server: ServerContext) => void;
stopWatcher: () => void;
generateRoutes: () => string;
generateResolver: () => string;
definePageTransform(code: string, id: string): unplugin0.Thenable<unplugin0.TransformResult>;
};
//#endregion
//#region src/experimental/data-loaders/auto-exports.d.ts
/**
* {@link AutoExportLoaders} options.
*/
interface AutoExportLoadersOptions {
/**
* Filter page components to apply the auto-export. Passed to `transform.filter.id`.
*/
transformFilter: StringFilter;
/**
* Globs to match the paths of the loaders.
*/
loadersPathsGlobs: string | string[];
/**
* Root of the project. All paths are resolved relatively to this one.
* @default `process.cwd()`
*/
root?: string;
}
/**
* Vite Plugin to automatically export loaders from page components.
*
* @param options Options
* @experimental - This API is experimental and can be changed in the future. It's used internally by `experimental.autoExportsDataLoaders`
*/
declare function AutoExportLoaders({
transformFilter,
loadersPathsGlobs,
root
}: AutoExportLoadersOptions): Plugin;
//#endregion
//#region src/unplugin/index.d.ts
declare const _default: unplugin0.UnpluginInstance<Options | undefined, boolean>;
/**
* Adds useful auto imports to the AutoImport config:
* @example
* ```js
* import { VueRouterAutoImports } from 'vue-router/unplugin'
*
* AutoImport({
* imports: [VueRouterAutoImports],
* }),
* ```
*/
declare const VueRouterAutoImports: Record<string, Array<string | [importName: string, alias: string]>>;
//#endregion
export { AutoExportLoaders, type AutoExportLoadersOptions, DEFAULT_OPTIONS, EditableTreeNode, type Options, type ParamParsersOptions, type ResolvedOptions, type RoutesFolder, type RoutesFolderOption, type RoutesFolderOptionResolved, type TreeNode, type TreeNodeValue, type TreeNodeValueGroup, type TreeNodeValueParam, type TreeNodeValueStatic, VueRouterAutoImports, createRoutesContext, createTreeNodeValue, _default as default, getFileBasedRouteName, getPascalCaseRouteName, resolveOptions };
+9
View File
@@ -0,0 +1,9 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { d as getPascalCaseRouteName, i as resolveOptions, t as DEFAULT_OPTIONS, u as getFileBasedRouteName } from "../options-DrVGtYpN.mjs";
import { a as EditableTreeNode, i as createRoutesContext, n as unplugin_default, o as createTreeNodeValue, r as AutoExportLoaders, t as VueRouterAutoImports } from "../unplugin-DuCbyUDD.mjs";
export { AutoExportLoaders, DEFAULT_OPTIONS, EditableTreeNode, VueRouterAutoImports, createRoutesContext, createTreeNodeValue, unplugin_default as default, getFileBasedRouteName, getPascalCaseRouteName, resolveOptions };
+12
View File
@@ -0,0 +1,12 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
const require_options = require('../options-CDXgA1NW.cjs');
exports.DEFAULT_OPTIONS = require_options.DEFAULT_OPTIONS;
exports.DEFAULT_PARAM_PARSERS_OPTIONS = require_options.DEFAULT_PARAM_PARSERS_OPTIONS;
exports.mergeAllExtensions = require_options.mergeAllExtensions;
exports.resolveOptions = require_options.resolveOptions;
exports.resolveOverridableOption = require_options.resolveOverridableOption;
+7
View File
@@ -0,0 +1,7 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { a as ResolvedOptions, c as RoutesFolderOptionResolved, d as _RoutesFolder, f as mergeAllExtensions, i as ParamParsersOptions, l as ServerContext, m as resolveOverridableOption, n as DEFAULT_PARAM_PARSERS_OPTIONS, o as RoutesFolder, p as resolveOptions, r as Options, s as RoutesFolderOption, t as DEFAULT_OPTIONS, u as _OverridableOption } from "../options-C8M2qFcl.cjs";
export { DEFAULT_OPTIONS, DEFAULT_PARAM_PARSERS_OPTIONS, Options, ParamParsersOptions, ResolvedOptions, RoutesFolder, RoutesFolderOption, RoutesFolderOptionResolved, ServerContext, _OverridableOption, _RoutesFolder, mergeAllExtensions, resolveOptions, resolveOverridableOption };
+7
View File
@@ -0,0 +1,7 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { a as ResolvedOptions, c as RoutesFolderOptionResolved, d as _RoutesFolder, f as mergeAllExtensions, i as ParamParsersOptions, l as ServerContext, m as resolveOverridableOption, n as DEFAULT_PARAM_PARSERS_OPTIONS, o as RoutesFolder, p as resolveOptions, r as Options, s as RoutesFolderOption, t as DEFAULT_OPTIONS, u as _OverridableOption } from "../options-rGD93PHF.mjs";
export { DEFAULT_OPTIONS, DEFAULT_PARAM_PARSERS_OPTIONS, Options, ParamParsersOptions, ResolvedOptions, RoutesFolder, RoutesFolderOption, RoutesFolderOptionResolved, ServerContext, _OverridableOption, _RoutesFolder, mergeAllExtensions, resolveOptions, resolveOverridableOption };
+8
View File
@@ -0,0 +1,8 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { a as resolveOverridableOption, i as resolveOptions, n as DEFAULT_PARAM_PARSERS_OPTIONS, r as mergeAllExtensions, t as DEFAULT_OPTIONS } from "../options-DrVGtYpN.mjs";
export { DEFAULT_OPTIONS, DEFAULT_PARAM_PARSERS_OPTIONS, mergeAllExtensions, resolveOptions, resolveOverridableOption };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
Object.defineProperty(exports, '__esModule', { value: true });
const require_unplugin = require('../unplugin-DL8B31Qb.cjs');
//#region src/unplugin/rolldown.ts
var rolldown_default = require_unplugin.unplugin_default.rolldown;
//#endregion
exports.default = rolldown_default;
+11
View File
@@ -0,0 +1,11 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-C8M2qFcl.cjs";
import * as rolldown0 from "rolldown";
//#region src/unplugin/rolldown.d.ts
declare const _default: (options?: Options | undefined) => rolldown0.Plugin<any> | rolldown0.Plugin<any>[];
export = _default;
+12
View File
@@ -0,0 +1,12 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-rGD93PHF.mjs";
import * as rolldown0 from "rolldown";
//#region src/unplugin/rolldown.d.ts
declare const _default: (options?: Options | undefined) => rolldown0.Plugin<any> | rolldown0.Plugin<any>[];
//#endregion
export { _default as default };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import "../options-DrVGtYpN.mjs";
import { n as unplugin_default } from "../unplugin-DuCbyUDD.mjs";
//#region src/unplugin/rolldown.ts
var rolldown_default = unplugin_default.rolldown;
//#endregion
export { rolldown_default as default };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
Object.defineProperty(exports, '__esModule', { value: true });
const require_unplugin = require('../unplugin-DL8B31Qb.cjs');
//#region src/unplugin/rollup.ts
var rollup_default = require_unplugin.unplugin_default.rollup;
//#endregion
exports.default = rollup_default;
+11
View File
@@ -0,0 +1,11 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-C8M2qFcl.cjs";
import * as rollup0 from "rollup";
//#region src/unplugin/rollup.d.ts
declare const _default: (options?: Options | undefined) => rollup0.Plugin<any> | rollup0.Plugin<any>[];
export = _default;
+12
View File
@@ -0,0 +1,12 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-rGD93PHF.mjs";
import * as rollup0 from "rollup";
//#region src/unplugin/rollup.d.ts
declare const _default: (options?: Options | undefined) => rollup0.Plugin<any> | rollup0.Plugin<any>[];
//#endregion
export { _default as default };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import "../options-DrVGtYpN.mjs";
import { n as unplugin_default } from "../unplugin-DuCbyUDD.mjs";
//#region src/unplugin/rollup.ts
var rollup_default = unplugin_default.rollup;
//#endregion
export { rollup_default as default };
+5
View File
@@ -0,0 +1,5 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
+7
View File
@@ -0,0 +1,7 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { S as TreeNodeValueStatic, b as TreeNodeValueGroup, h as EditableTreeNode, r as Options, v as TreeNode, x as TreeNodeValueParam, y as TreeNodeValue } from "../options-C8M2qFcl.cjs";
export { type EditableTreeNode, type Options, type TreeNode, type TreeNodeValue, type TreeNodeValueGroup, type TreeNodeValueParam, type TreeNodeValueStatic };
+7
View File
@@ -0,0 +1,7 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { S as TreeNodeValueStatic, b as TreeNodeValueGroup, h as EditableTreeNode, r as Options, v as TreeNode, x as TreeNodeValueParam, y as TreeNodeValue } from "../options-rGD93PHF.mjs";
export { type EditableTreeNode, type Options, type TreeNode, type TreeNodeValue, type TreeNodeValueGroup, type TreeNodeValueParam, type TreeNodeValueStatic };
+6
View File
@@ -0,0 +1,6 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
export { };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
Object.defineProperty(exports, '__esModule', { value: true });
const require_unplugin = require('../unplugin-DL8B31Qb.cjs');
//#region src/unplugin/vite.ts
var vite_default = require_unplugin.unplugin_default.vite;
//#endregion
exports.default = vite_default;
+11
View File
@@ -0,0 +1,11 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-C8M2qFcl.cjs";
import * as vite0 from "vite";
//#region src/unplugin/vite.d.ts
declare const _default: (options?: Options | undefined) => vite0.Plugin<any> | vite0.Plugin<any>[];
export = _default;
+12
View File
@@ -0,0 +1,12 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-rGD93PHF.mjs";
import * as vite0 from "vite";
//#region src/unplugin/vite.d.ts
declare const _default: (options?: Options | undefined) => vite0.Plugin<any> | vite0.Plugin<any>[];
//#endregion
export { _default as default };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import "../options-DrVGtYpN.mjs";
import { n as unplugin_default } from "../unplugin-DuCbyUDD.mjs";
//#region src/unplugin/vite.ts
var vite_default = unplugin_default.vite;
//#endregion
export { vite_default as default };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
Object.defineProperty(exports, '__esModule', { value: true });
const require_unplugin = require('../unplugin-DL8B31Qb.cjs');
//#region src/unplugin/webpack.ts
var webpack_default = require_unplugin.unplugin_default.webpack;
//#endregion
exports.default = webpack_default;
+10
View File
@@ -0,0 +1,10 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-C8M2qFcl.cjs";
//#region src/unplugin/webpack.d.ts
declare const _default: (options?: Options | undefined) => WebpackPluginInstance;
export = _default;
+11
View File
@@ -0,0 +1,11 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { r as Options } from "../options-rGD93PHF.mjs";
//#region src/unplugin/webpack.d.ts
declare const _default: (options?: Options | undefined) => WebpackPluginInstance;
//#endregion
export { _default as default };
+13
View File
@@ -0,0 +1,13 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import "../options-DrVGtYpN.mjs";
import { n as unplugin_default } from "../unplugin-DuCbyUDD.mjs";
//#region src/unplugin/webpack.ts
var webpack_default = unplugin_default.webpack;
//#endregion
export { webpack_default as default };
+201
View File
@@ -0,0 +1,201 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { inject } from "vue";
//#region src/utils/env.ts
const isBrowser = typeof document !== "undefined";
//#endregion
//#region src/utils/index.ts
/**
* Identity function that returns the value as is.
*
* @param v - the value to return
*
* @internal
*/
const identityFn = (v) => v;
/**
* Allows differentiating lazy components from functional components and vue-class-component
* @internal
*
* @param component
*/
function isRouteComponent(component) {
return typeof component === "object" || "displayName" in component || "props" in component || "__vccOpts" in component;
}
function isESModule(obj) {
return obj.__esModule || obj[Symbol.toStringTag] === "Module" || obj.default && isRouteComponent(obj.default);
}
const assign = Object.assign;
function applyToParams(fn, params) {
const newParams = {};
for (const key in params) {
const value = params[key];
newParams[key] = isArray(value) ? value.map(fn) : fn(value);
}
return newParams;
}
const noop = () => {};
/**
* Typesafe alternative to Array.isArray
* https://github.com/microsoft/TypeScript/pull/48228
*
* @internal
*/
const isArray = Array.isArray;
function mergeOptions(defaults, partialOptions) {
const options = {};
for (const key in defaults) options[key] = key in partialOptions ? partialOptions[key] : defaults[key];
return options;
}
//#endregion
//#region src/errors.ts
/**
* Flags so we can combine them when checking for multiple errors. This is the internal version of
* {@link NavigationFailureType}.
*
* @internal
*/
let ErrorTypes = /* @__PURE__ */ function(ErrorTypes) {
ErrorTypes[ErrorTypes["MATCHER_NOT_FOUND"] = 1] = "MATCHER_NOT_FOUND";
ErrorTypes[ErrorTypes["NAVIGATION_GUARD_REDIRECT"] = 2] = "NAVIGATION_GUARD_REDIRECT";
ErrorTypes[ErrorTypes["NAVIGATION_ABORTED"] = 4] = "NAVIGATION_ABORTED";
ErrorTypes[ErrorTypes["NAVIGATION_CANCELLED"] = 8] = "NAVIGATION_CANCELLED";
ErrorTypes[ErrorTypes["NAVIGATION_DUPLICATED"] = 16] = "NAVIGATION_DUPLICATED";
return ErrorTypes;
}({});
const NavigationFailureSymbol = Symbol(process.env.NODE_ENV !== "production" ? "navigation failure" : "");
/**
* Enumeration with all possible types for navigation failures. Can be passed to
* {@link isNavigationFailure} to check for specific failures.
*/
let NavigationFailureType = /* @__PURE__ */ function(NavigationFailureType) {
/**
* An aborted navigation is a navigation that failed because a navigation
* guard returned `false` or called `next(false)`
*/
NavigationFailureType[NavigationFailureType["aborted"] = 4] = "aborted";
/**
* A cancelled navigation is a navigation that failed because a more recent
* navigation finished started (not necessarily finished).
*/
NavigationFailureType[NavigationFailureType["cancelled"] = 8] = "cancelled";
/**
* A duplicated navigation is a navigation that failed because it was
* initiated while already being at the exact same location.
*/
NavigationFailureType[NavigationFailureType["duplicated"] = 16] = "duplicated";
return NavigationFailureType;
}({});
const ErrorTypeMessages = {
[ErrorTypes.MATCHER_NOT_FOUND]({ location, currentLocation }) {
return `No match for\n ${JSON.stringify(location)}${currentLocation ? "\nwhile being at\n" + JSON.stringify(currentLocation) : ""}`;
},
[ErrorTypes.NAVIGATION_GUARD_REDIRECT]({ from, to }) {
return `Redirected from "${from.fullPath}" to "${stringifyRoute(to)}" via a navigation guard.`;
},
[ErrorTypes.NAVIGATION_ABORTED]({ from, to }) {
return `Navigation aborted from "${from.fullPath}" to "${to.fullPath}" via a navigation guard.`;
},
[ErrorTypes.NAVIGATION_CANCELLED]({ from, to }) {
return `Navigation cancelled from "${from.fullPath}" to "${to.fullPath}" with a new navigation.`;
},
[ErrorTypes.NAVIGATION_DUPLICATED]({ from, to: _to }) {
return `Avoided redundant navigation to current location: "${from.fullPath}".`;
}
};
/**
* Creates a typed NavigationFailure object.
* @internal
* @param type - NavigationFailureType
* @param params - { from, to }
*/
function createRouterError(type, params) {
if (process.env.NODE_ENV !== "production" || false) return assign(new Error(ErrorTypeMessages[type](params)), {
type,
[NavigationFailureSymbol]: true
}, params);
else return assign(/* @__PURE__ */ new Error(), {
type,
[NavigationFailureSymbol]: true
}, params);
}
function isNavigationFailure(error, type) {
return error instanceof Error && NavigationFailureSymbol in error && (type == null || !!(error.type & type));
}
const propertiesToLog = [
"params",
"query",
"hash"
];
function stringifyRoute(to) {
if (typeof to === "string") return to;
if (to.path != null) return to.path;
const location = {};
for (const key of propertiesToLog) if (key in to) location[key] = to[key];
return JSON.stringify(location, null, 2);
}
//#endregion
//#region src/injectionSymbols.ts
/**
* RouteRecord being rendered by the closest ancestor Router View. Used for
* `onBeforeRouteUpdate` and `onBeforeRouteLeave`. rvlm stands for Router View
* Location Matched
*
* @internal
*/
const matchedRouteKey = Symbol(process.env.NODE_ENV !== "production" ? "router view location matched" : "");
/**
* Allows overriding the router view depth to control which component in
* `matched` is rendered. rvd stands for Router View Depth
*
* @internal
*/
const viewDepthKey = Symbol(process.env.NODE_ENV !== "production" ? "router view depth" : "");
/**
* Allows overriding the router instance returned by `useRouter` in tests. r
* stands for router
*
* @internal
*/
const routerKey = Symbol(process.env.NODE_ENV !== "production" ? "router" : "");
/**
* Allows overriding the current route returned by `useRoute` in tests. rl
* stands for route location
*
* @internal
*/
const routeLocationKey = Symbol(process.env.NODE_ENV !== "production" ? "route location" : "");
/**
* Allows overriding the current route used by router-view. Internally this is
* used when the `route` prop is passed.
*
* @internal
*/
const routerViewLocationKey = Symbol(process.env.NODE_ENV !== "production" ? "router view location" : "");
//#endregion
//#region src/useApi.ts
/**
* Returns the router instance. Equivalent to using `$router` inside
* templates.
*/
function useRouter() {
return inject(routerKey);
}
/**
* Returns the current route location. Equivalent to using `$route` inside
* templates.
*/
function useRoute(_name) {
return inject(routeLocationKey);
}
//#endregion
export { isRouteComponent as _, routerKey as a, isBrowser as b, ErrorTypes as c, isNavigationFailure as d, applyToParams as f, isESModule as g, isArray as h, routeLocationKey as i, NavigationFailureType as l, identityFn as m, useRouter as n, routerViewLocationKey as o, assign as p, matchedRouteKey as r, viewDepthKey as s, useRoute as t, createRouterError as u, mergeOptions as v, noop as y };
+52
View File
@@ -0,0 +1,52 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
let _vue_language_core = require("@vue/language-core");
let muggle_string = require("muggle-string");
//#region src/volar/entries/sfc-route-blocks.ts
const plugin = () => {
const routeBlockIdPrefix = "route_";
const routeBlockIdRe = new RegExp(`^${routeBlockIdPrefix}(\\d+)$`);
return {
version: 2.1,
getEmbeddedCodes(_fileName, sfc) {
const embeddedCodes = [];
for (let i = 0; i < sfc.customBlocks.length; i++) {
const block = sfc.customBlocks[i];
if (block.type === "route") {
const lang = block.lang === "txt" ? "json" : block.lang;
embeddedCodes.push({
id: `${routeBlockIdPrefix}${i}`,
lang
});
}
}
return embeddedCodes;
},
resolveEmbeddedCode(_fileName, sfc, embeddedCode) {
const match = embeddedCode.id.match(routeBlockIdRe);
if (match) {
const i = parseInt(match[1]);
const block = sfc.customBlocks[i];
if (!block) return;
embeddedCode.content.push([
block.content,
block.name,
0,
_vue_language_core.allCodeFeatures
]);
if (embeddedCode.lang === "json") {
const contentStr = (0, muggle_string.toString)(embeddedCode.content);
if (contentStr.trim().startsWith("{") && !contentStr.includes("$schema")) (0, muggle_string.replace)(embeddedCode.content, "{", "{\n \"$schema\": \"https://router.vuejs.org/schemas/route.schema.json\",");
}
}
}
};
};
var sfc_route_blocks_default = plugin;
//#endregion
module.exports = sfc_route_blocks_default;
+10
View File
@@ -0,0 +1,10 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { VueLanguagePlugin } from "@vue/language-core";
//#region src/volar/entries/sfc-route-blocks.d.ts
declare const plugin: VueLanguagePlugin;
export = plugin;
+71
View File
@@ -0,0 +1,71 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
let muggle_string = require("muggle-string");
let pathe = require("pathe");
//#region src/volar/utils/augment-vls-ctx.ts
/**
* Augments the VLS context (volar) with additianal type information.
*
* @param content - content retrieved from the volar pluign
* @param codes - codes to add to the VLS context
*/
function augmentVlsCtx(content, codes) {
let from = -1;
for (let i = 0; i < content.length; i++) {
const code = content[i];
if (typeof code !== "string") continue;
if (from === -1 && code.startsWith(`const __VLS_ctx`)) from = i;
else if (from !== -1) {
if (code === `}`) {
content.splice(i, 0, ...codes.map((code) => `...${code},\n`));
break;
} else if (code === `;\n`) {
content.splice(from + 1, i - from, `{\n`, `...`, ...content.slice(from + 1, i), `,\n`, ...codes.map((code) => `...${code},\n`), `}`, `;\n`);
break;
}
}
}
}
//#endregion
//#region src/volar/entries/sfc-typed-router.ts
const plugin = ({ compilerOptions, modules: { typescript: ts }, config: { options } }) => {
const rootDir = options?.rootDir ?? compilerOptions.rootDir;
if (!rootDir) console.warn("[vue-router] No rootDir specified. Set it in the Volar plugin options or tsconfig compilerOptions.rootDir for proper typed routes.");
const RE = { DOLLAR_ROUTE: { VLS_CTX: /\b__VLS_ctx.\$route\b/g } };
return {
version: 2.1,
resolveEmbeddedCode(fileName, sfc, embeddedCode) {
if (!embeddedCode.id.startsWith("script_")) return;
const useRouteNameTypeParam = `<${`import('vue-router/auto-routes')._RouteNamesForFilePath<'${rootDir ? (0, pathe.relative)(rootDir, fileName) : fileName}'>`}>`;
if (sfc.scriptSetup) visit(sfc.scriptSetup.ast);
function visit(node) {
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && ts.idText(node.expression) === "useRoute" && !node.typeArguments && !node.arguments.length) if (!sfc.scriptSetup.lang.startsWith("js")) (0, muggle_string.replaceSourceRange)(embeddedCode.content, sfc.scriptSetup.name, node.expression.end, node.expression.end, useRouteNameTypeParam);
else {
const { start, end } = getStartEnd(node, sfc.scriptSetup.ast);
(0, muggle_string.replaceSourceRange)(embeddedCode.content, sfc.scriptSetup.name, start, start, `(`);
(0, muggle_string.replaceSourceRange)(embeddedCode.content, sfc.scriptSetup.name, end, end, ` as ReturnType<typeof useRoute${useRouteNameTypeParam}>)`);
}
else ts.forEachChild(node, visit);
}
const contentStr = (0, muggle_string.toString)(embeddedCode.content);
const vlsCtxAugmentations = [];
if (contentStr.match(RE.DOLLAR_ROUTE.VLS_CTX)) vlsCtxAugmentations.push(`{} as { $route: ReturnType<typeof import('vue-router').useRoute${useRouteNameTypeParam}> }`);
if (vlsCtxAugmentations.length) augmentVlsCtx(embeddedCode.content, vlsCtxAugmentations);
}
};
function getStartEnd(node, ast) {
return {
start: ts.getTokenPosOfNode(node, ast),
end: node.end
};
}
};
var sfc_typed_router_default = plugin;
//#endregion
module.exports = sfc_typed_router_default;
+14
View File
@@ -0,0 +1,14 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { VueLanguagePlugin } from "@vue/language-core";
//#region src/volar/entries/sfc-typed-router.d.ts
declare const plugin: VueLanguagePlugin<{
options?: {
rootDir?: string;
};
}>;
export = plugin;
+2788
View File
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
/*!
* vue-router v5.0.6
* (c) 2026 Eduardo San Martin Morote
* @license MIT
*/
import { $t as ParamValueZeroOrMore, An as RouterHistory, At as RouteLocationGeneric, Bn as LocationQueryValueRaw, Bt as RouteLocationResolved, Cn as RouteRecordRaw, Ct as RouteLocationAsRelative, Dn as _RouteLocationBase, Dt as RouteLocationAsString, En as RouteRecordSingleViewWithChildren, Et as RouteLocationAsRelativeTypedList, Fn as RouteRecord, Ft as RouteLocationNormalizedLoadedTyped, G as START_LOCATION_NORMALIZED, Gt as RouteLocationTypedList, Hn as stringifyQuery, Ht as RouteLocationResolvedTyped, In as RouteRecordNormalized, It as RouteLocationNormalizedLoadedTypedList, Jt as RouteRecordRedirectOption, Kt as RouteRecordName, Ln as LocationQuery, Lt as RouteLocationNormalizedTyped, Mn as createRouterMatcher, Mt as RouteLocationNormalizedGeneric, Nn as PathParserOptions, Nt as RouteLocationNormalizedLoaded, On as _RouteRecordBase, Ot as RouteLocationAsStringTyped, Pn as _PathParserOptions, Pt as RouteLocationNormalizedLoadedGeneric, Qt as ParamValueOneOrMore, Rn as LocationQueryRaw, Rt as RouteLocationNormalizedTypedList, Sn as RouteRecordMultipleViewsWithChildren, St as RouteLocationAsPathTypedList, Tn as RouteRecordSingleView, Tt as RouteLocationAsRelativeTyped, Un as TypesConfig, Ut as RouteLocationResolvedTypedList, Vn as parseQuery, Vt as RouteLocationResolvedGeneric, Wt as RouteLocationTyped, Xt as _Awaitable, Yt as _RouteRecordProps, Zt as ParamValue, _ as routerViewLocationKey, _n as RouteParamValueRaw, _t as isNavigationFailure, a as RouterLink, an as RouteRecordInfo, at as createMemoryHistory, b as RouterOptions, bn as RouteQueryAndHash, bt as RouteLocationAsPathGeneric, c as UseLinkReturn, cn as MatcherLocation, ct as NavigationGuardNext, d as loadRouteLocation, dn as RouteLocationMatched, dt as NavigationGuardWithThis, en as ParamValueZeroOrOne, f as onBeforeRouteLeave, fn as RouteLocationNamedRaw, ft as NavigationHookAfter, g as routerKey, gn as RouteParamValue, gt as NavigationRedirectError, h as routeLocationKey, hn as RouteMeta, ht as NavigationFailureType, i as RouterViewProps, in as RouteMapGeneric, it as createWebHashHistory, jn as RouterMatcher, jt as RouteLocationNormalized, kn as HistoryState, kt as RouteLocationAsStringTypedList, l as _RouterLinkI, ln as MatcherLocationAsPath, lt as NavigationGuardNextCallback, m as matchedRouteKey, mn as RouteLocationPathRaw, mt as NavigationFailure, n as useRouter, nn as RouteParamsRaw, o as RouterLinkProps, on as RouteRecordInfoGeneric, ot as createWebHistory, p as onBeforeRouteUpdate, pn as RouteLocationOptions, pt as ErrorTypes, qt as RouteRecordNameGeneric, r as RouterView, rn as RouteMap, rt as RouterScrollBehavior, s as UseLinkOptions, sn as LocationAsRelativeRaw, st as NavigationGuard, t as useRoute, tn as RouteParams, u as useLink, un as RouteComponent, ut as NavigationGuardReturn, v as viewDepthKey, vn as RouteParamsGeneric, vt as RouteLocation, wn as RouteRecordRedirect, wt as RouteLocationAsRelativeGeneric, x as createRouter, xn as RouteRecordMultipleViews, xt as RouteLocationAsPathTyped, y as Router, yn as RouteParamsRawGeneric, yt as RouteLocationAsPath, zn as LocationQueryValue, zt as RouteLocationRaw } from "./index-D_VEAp3P.js";
export { ErrorTypes, HistoryState, LocationAsRelativeRaw, LocationQuery, LocationQueryRaw, LocationQueryValue, LocationQueryValueRaw, MatcherLocation, MatcherLocationAsPath, NavigationFailure, NavigationFailureType, NavigationGuard, NavigationGuardNext, NavigationGuardNextCallback, NavigationGuardReturn, NavigationGuardWithThis, NavigationHookAfter, NavigationRedirectError, ParamValue, ParamValueOneOrMore, ParamValueZeroOrMore, ParamValueZeroOrOne, PathParserOptions, RouteComponent, RouteLocation, RouteLocationAsPath, RouteLocationAsPathGeneric, RouteLocationAsPathTyped, RouteLocationAsPathTypedList, RouteLocationAsRelative, RouteLocationAsRelativeGeneric, RouteLocationAsRelativeTyped, RouteLocationAsRelativeTypedList, RouteLocationAsString, RouteLocationAsStringTyped, RouteLocationAsStringTypedList, RouteLocationGeneric, RouteLocationMatched, RouteLocationNamedRaw, RouteLocationNormalized, RouteLocationNormalizedGeneric, RouteLocationNormalizedLoaded, RouteLocationNormalizedLoadedGeneric, RouteLocationNormalizedLoadedTyped, RouteLocationNormalizedLoadedTypedList, RouteLocationNormalizedTyped, RouteLocationNormalizedTypedList, RouteLocationOptions, RouteLocationPathRaw, RouteLocationRaw, RouteLocationResolved, RouteLocationResolvedGeneric, RouteLocationResolvedTyped, RouteLocationResolvedTypedList, RouteLocationTyped, RouteLocationTypedList, RouteMap, RouteMapGeneric, RouteMeta, RouteParamValue, RouteParamValueRaw, RouteParams, RouteParamsGeneric, RouteParamsRaw, RouteParamsRawGeneric, RouteQueryAndHash, RouteRecord, RouteRecordInfo, RouteRecordInfoGeneric, RouteRecordMultipleViews, RouteRecordMultipleViewsWithChildren, RouteRecordName, RouteRecordNameGeneric, RouteRecordNormalized, RouteRecordRaw, RouteRecordRedirect, RouteRecordRedirectOption, RouteRecordSingleView, RouteRecordSingleViewWithChildren, Router, RouterHistory, RouterLink, RouterLinkProps, RouterMatcher, RouterOptions, RouterScrollBehavior, RouterView, RouterViewProps, START_LOCATION_NORMALIZED as START_LOCATION, TypesConfig, UseLinkOptions, UseLinkReturn, _Awaitable, _PathParserOptions, _RouteLocationBase, _RouteRecordBase, _RouteRecordProps, _RouterLinkI, createMemoryHistory, createRouter, createRouterMatcher, createWebHashHistory, createWebHistory, isNavigationFailure, loadRouteLocation, matchedRouteKey, onBeforeRouteLeave, onBeforeRouteUpdate, parseQuery, routeLocationKey, routerKey, routerViewLocationKey, stringifyQuery, useLink, useRoute, useRouter, viewDepthKey };
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
console.warn("[vue-router]: importing from 'vue-router/dist/vue-router.esm-bundler.js' is deprecated. Use 'vue-router' directly.")
export * from './vue-router.js'
+2437
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+1540
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+7
View File
@@ -0,0 +1,7 @@
'use strict'
if (process.env.NODE_ENV === 'production') {
module.exports = require('./dist/vue-router.prod.cjs')
} else {
module.exports = require('./dist/vue-router.cjs')
}
+222
View File
@@ -0,0 +1,222 @@
{
"name": "vue-router",
"version": "5.0.6",
"homepage": "https://router.vuejs.org",
"bugs": {
"url": "https://github.com/vuejs/router/issues"
},
"license": "MIT",
"author": {
"name": "Eduardo San Martin Morote",
"email": "posva13@gmail.com"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/router.git"
},
"funding": "https://github.com/sponsors/posva",
"files": [
"dist",
"index.cjs",
"README.md",
"route.schema.json",
"vue-router-auto-resolver.d.mts",
"vue-router-auto-routes.d.mts",
"vue-router-auto.d.ts",
"vue-router.node.mjs",
"vetur/attributes.json",
"vetur/tags.json"
],
"type": "module",
"sideEffects": false,
"main": "index.cjs",
"module": "dist/vue-router.js",
"types": "dist/vue-router.d.ts",
"typesVersions": {
"*": {
"vite": [
"./dist/unplugin/vite.d.mts"
],
"unplugin": [
"./dist/unplugin/index.d.mts"
],
"unplugin/*": [
"./dist/unplugin/*.d.mts"
],
"volar/*": [
"./dist/volar/*.d.cts"
]
}
},
"unpkg": "dist/vue-router.global.js",
"jsdelivr": "dist/vue-router.global.js",
"exports": {
".": {
"types": "./dist/vue-router.d.ts",
"node": {
"import": {
"production": "./vue-router.node.mjs",
"development": "./vue-router.node.mjs",
"default": "./vue-router.node.mjs"
},
"require": {
"production": "./dist/vue-router.prod.cjs",
"development": "./dist/vue-router.cjs",
"default": "./index.cjs"
}
},
"import": "./dist/vue-router.js",
"require": "./index.cjs"
},
"./dist/*": "./dist/*",
"./vetur/*": "./vetur/*",
"./package.json": "./package.json",
"./experimental": {
"types": "./dist/experimental/index.d.ts",
"default": "./dist/experimental/index.js"
},
"./experimental/pinia-colada": {
"types": "./dist/experimental/pinia-colada.d.ts",
"default": "./dist/experimental/pinia-colada.js"
},
"./auto-resolver": {
"types": "./vue-router-auto-resolver.d.mts"
},
"./auto-routes": {
"types": "./vue-router-auto-routes.d.mts"
},
"./auto": {
"types": "./vue-router-auto.d.ts",
"node": {
"import": {
"production": "./vue-router.node.mjs",
"development": "./vue-router.node.mjs",
"default": "./vue-router.node.mjs"
},
"require": {
"production": "./dist/vue-router.prod.cjs",
"development": "./dist/vue-router.cjs",
"default": "./index.cjs"
}
},
"import": "./dist/vue-router.js",
"require": "./index.cjs"
},
"./vite": {
"types": "./dist/unplugin/vite.d.mts",
"import": "./dist/unplugin/vite.mjs",
"require": "./dist/unplugin/vite.cjs"
},
"./unplugin": {
"types": "./dist/unplugin/index.d.mts",
"import": "./dist/unplugin/index.mjs",
"require": "./dist/unplugin/index.cjs"
},
"./unplugin/*": "./dist/unplugin/*",
"./volar/sfc-route-blocks": {
"types": "./dist/volar/sfc-route-blocks.d.cts",
"default": "./dist/volar/sfc-route-blocks.cjs"
},
"./volar/sfc-typed-router": {
"types": "./dist/volar/sfc-typed-router.d.cts",
"default": "./dist/volar/sfc-typed-router.cjs"
}
},
"dependencies": {
"@babel/generator": "^7.28.6",
"@vue-macros/common": "^3.1.1",
"@vue/devtools-api": "^8.0.6",
"ast-walker-scope": "^0.8.3",
"chokidar": "^5.0.0",
"json5": "^2.2.3",
"local-pkg": "^1.1.2",
"magic-string": "^0.30.21",
"mlly": "^1.8.0",
"muggle-string": "^0.4.1",
"pathe": "^2.0.3",
"picomatch": "^4.0.3",
"scule": "^1.3.0",
"tinyglobby": "^0.2.15",
"unplugin": "^3.0.0",
"unplugin-utils": "^0.3.1",
"yaml": "^2.8.2"
},
"devDependencies": {
"@babel/types": "^7.29.0",
"@pinia/colada": "^0.21.2",
"@playwright/test": "^1.58.1",
"@rollup/plugin-commonjs": "^28.0.9",
"@rollup/plugin-node-resolve": "^16.0.3",
"@rollup/plugin-replace": "^6.0.3",
"@rollup/plugin-terser": "^0.4.4",
"@standard-schema/spec": "^1.1.0",
"@types/babel__generator": "^7.27.0",
"@types/nightwatch": "^2.3.32",
"@types/picomatch": "^4.0.2",
"@typescript/native-preview": "7.0.0-dev.20260106.1",
"@vitejs/plugin-vue": "^6.0.4",
"@vue/compiler-sfc": "3.6.0-beta.2",
"@vue/language-core": "^3.2.1",
"@vue/server-renderer": "3.6.0-beta.2",
"@vue/test-utils": "^2.4.6",
"browserstack-local": "^1.5.8",
"chromedriver": "^144.0.1",
"connect-history-api-fallback": "^2.0.0",
"dotenv": "^17.2.3",
"faked-promise": "^2.2.2",
"geckodriver": "^6.1.0",
"happy-dom": "^20.5.0",
"nightwatch": "^3.15.0",
"nightwatch-helpers": "^1.2.0",
"pinia": "^3.0.4",
"rimraf": "^6.1.2",
"rollup": "^4.57.1",
"rollup-plugin-typescript2": "^0.36.0",
"tsdown": "^0.20.1",
"tsup": "^8.5.1",
"valibot": "^1.3.1",
"vite": "^7.3.0",
"vue": "3.6.0-beta.2",
"zod": "^4.3.6"
},
"peerDependencies": {
"@pinia/colada": ">=0.21.2",
"@vue/compiler-sfc": "^3.5.17",
"pinia": "^3.0.4",
"vue": "^3.5.0"
},
"peerDependenciesMeta": {
"@vue/compiler-sfc": {
"optional": true
},
"pinia": {
"optional": true
},
"@pinia/colada": {
"optional": true
}
},
"vetur": {
"tags": "vetur/tags.json",
"attributes": "vetur/attributes.json"
},
"scripts": {
"dev": "vitest --ui",
"build": "tsdown",
"build:old": "rimraf dist && rollup -c rollup.config.mjs",
"build:playground": "vue-tsc --noEmit && vite build --config playground/vite.config.ts",
"build:e2e": "vue-tsc --noEmit && vite build --config e2e/vite.config.mjs",
"build:size": "pnpm run build && rollup -c size-checks/rollup.config.mjs",
"dev:e2e": "vite --config e2e/vite.config.mjs",
"test:types": "tsc --build tsconfig.json",
"test:unit": "vitest --coverage run",
"test": "pnpm run '/^(build|test:types)$/' && pnpm run '/^test:(unit|e2e|e2e:hmr)$/'",
"test:e2e": "pnpm run test:e2e:headless",
"test:e2e:hmr": "pnpm exec playwright test",
"test:e2e:headless": "node e2e/runner.mjs --env chrome-headless",
"test:e2e:native": "node e2e/runner.mjs --env chrome",
"test:e2e:ci": "node e2e/runner.mjs --env chrome-headless --retries 2",
"test:e2e:bs": "node e2e/runner.mjs --local -e android5 --tag browserstack",
"test:e2e:bs-test": "node e2e/runner.mjs --local --env browserstack.local_chrome --tag browserstack"
}
}
+25
View File
@@ -0,0 +1,25 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/posva/unplugin-vue-router/main/route.schema.json",
"title": "Route custom block",
"description": "An SFC custom block to add information to a route",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the route"
},
"path": {
"type": "string",
"description": "The path of the route"
},
"meta": {
"type": "object",
"description": "The meta of the route"
},
"props": {
"type": "boolean",
"description": "Whether the route should be passed its params as props"
}
}
}
+32
View File
@@ -0,0 +1,32 @@
{
"name": {
"type": "string | symbol",
"description": "When a `<router-view>` has a `name` prop, it will render the component with the corresponding name in the matched route record's components option."
},
"route": {
"description": "When a `<router-view>` has a `route` prop, it will use that resolved Route Location instead of the current location."
},
"to": {
"description": "Denotes the target route of the link. When clicked, the value of the `to` prop will be internally passed to `router.push()`, so the value can be either a string or a location descriptor object."
},
"replace": {
"type": "boolean",
"description": "Setting replace prop will call `router.replace()` instead of `router.push()` when clicked, so the navigation will replace the current history entry."
},
"custom": {
"type": "boolean",
"description": "Whether `<router-link>` should not wrap its content in an `<a>` tag."
},
"active-class": {
"type": "string",
"description": "Configure the active CSS class applied when the link is active. Note the default value can also be configured globally via the `linkActiveClass` router constructor option."
},
"exact-active-class": {
"type": "string",
"description": "Configure the active CSS class applied when the link is exactly active. Note the default value can also be configured globally via the `linkExactActiveClass` router constructor option."
},
"aria-current-value": {
"options": ["page", "step", "location", "date", "time", "true", "false"],
"description": "Configure the value of `aria-current` when the link is active with exact match. It must be one of the [allowed values for `aria-current`](https://www.w3.org/TR/wai-aria-1.2/#aria-current) in the ARIA spec. In most cases, the default of `page` should be the best fit."
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"router-view": {
"attributes": ["name", "route"],
"description": "Component that renders the matched component for the current location. Components rendered by `<router-view>` can also contain their own `<router-view>` to render nested routes."
},
"router-link": {
"attributes": [
"to",
"replace",
"custom",
"active-class",
"exact-active-class",
"aria-current-value"
],
"description": "Component that renders an `<a>` with the correct `href` attribute and click listeners to trigger a local navigation when clicked. Can also customize its rendering by providing the `custom` prop and using its `v-slot` API."
}
}
+27
View File
@@ -0,0 +1,27 @@
/**
* TODO: remove the declaration if possible when merging unplugin-vue-router
* into this monorepo in v6
*/
import type {
EXPERIMENTAL_Router,
EXPERIMENTAL_RouterOptions,
} from 'vue-router/experimental'
/**
* Handles HMR.
* Generated by unplugin-vue-router
*/
export function handleHotUpdate(router: EXPERIMENTAL_Router): void
/**
* Custom resolver automatically generated at build time
* Generated by unplugin-vue-router
*/
export declare const resolver: EXPERIMENTAL_RouterOptions['resolver']
// TODO:move to the generated route map so it can import the correct version (custom resolvers or not)
// Make the macros globally available
// declare global {
// const definePage: (typeof import("vue-router/experimental"))["definePage"];
// }
+46
View File
@@ -0,0 +1,46 @@
import type { Router, RouteRecordRaw } from 'vue-router'
/**
* Array of routes generated by vue-router file based routing
*/
export declare const routes: RouteRecordRaw[]
/**
* Setups hot module replacement for routes.
*
* @param router - The router instance
* @param hotUpdateCallback - Callback to be called after replacing the routes and before the navigation
*
* @example
*
* ```ts
* import { createRouter, createWebHistory } from 'vue-router'
* import { routes, handleHotUpdate } from 'vue-router/auto-routes'
* const router = createRouter({
* history: createWebHistory(),
* routes,
* })
* if (import.meta.hot) {
* handleHotUpdate(router)
* }
* ```
*/
export declare function handleHotUpdate(
router: Router,
hotUpdateCallback?: (newRoutes: RouteRecordRaw[]) => void
): void
// TODO: rename to RouteMap and move directly into vue-router so
// it can be extended with declare module 'vue-router'
export interface RouteNamedMap {}
declare module 'vue-router' {
interface TypesConfig {
RouteNamedMap: RouteNamedMap
}
}
// Make the macros globally available
declare global {
const definePage: (typeof import('vue-router/experimental'))['definePage']
}
+2
View File
@@ -0,0 +1,2 @@
// DEPRECATED: will be removed in future versions
// This file is augmented by the file-based routing plugin (vue-router/vite or vue-router/unplugin)
+2
View File
@@ -0,0 +1,2 @@
global.__VUE_PROD_DEVTOOLS__ = false
export * from './dist/vue-router.js'