penambahan web socket
This commit is contained in:
No files matched your search
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 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.
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
# unplugin-vue-router
|
||||
|
||||
[](https://www.npmjs.com/package/unplugin-vue-router) [](https://github.com/posva/unplugin-vue-router/actions/workflows/ci.yml) [](https://codecov.io/gh/posva/unplugin-vue-router)
|
||||
|
||||
> Automatic file based Routing in Vue with TS support ✨
|
||||
|
||||
<!-- https://user-images.githubusercontent.com/664177/176622756-3d10acc6-caac-40ff-a41f-9bdccadf7f1d.mp4 -->
|
||||
|
||||
<p align="center">
|
||||
<img src="https://user-images.githubusercontent.com/664177/176623167-0153f9fb-79cd-49a7-8575-429ce323dd11.gif" >
|
||||
</p>
|
||||
|
||||
- [StackBlitz Demo](https://stackblitz.com/github/posva/uvr-demo)
|
||||
|
||||
This build-time plugin simplifies your routing setup **and** makes it safer and easier to use thanks to TypeScript. Requires Vue Router >=4.4.0.
|
||||
|
||||
> [!WARNING]
|
||||
> While unplugin-vue-router typed routing and file based routing is fundamentally stable, it contains other experimental APIs that are subject to change (e.g. Data Loaders). Make sure to check the relevant [Documentation](https://uvr.esm.is) for the latest information.
|
||||
> If you find any issue, design flaw, or have ideas to improve it, please, open open an [issue](https://github.com/posva/unplugin-vue-router/issues/new/choose) or a [Discussion](https://github.com/posva/unplugin-vue-router/discussions).
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm i -D unplugin-vue-router
|
||||
```
|
||||
|
||||
Add VueRouter plugin **before** Vue plugin:
|
||||
|
||||
<details>
|
||||
<summary>Vite</summary><br>
|
||||
|
||||
```ts
|
||||
// vite.config.ts
|
||||
import VueRouter from 'unplugin-vue-router/vite'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
VueRouter({
|
||||
/* options */
|
||||
}),
|
||||
// ⚠️ Vue must be placed after VueRouter()
|
||||
Vue(),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
Example: [`playground/`](./playground/)
|
||||
|
||||
<br></details>
|
||||
|
||||
<details>
|
||||
<summary>Rollup</summary><br>
|
||||
|
||||
```ts
|
||||
// rollup.config.js
|
||||
import VueRouter from 'unplugin-vue-router/rollup'
|
||||
|
||||
export default {
|
||||
plugins: [
|
||||
VueRouter({
|
||||
/* options */
|
||||
}),
|
||||
// ⚠️ Vue must be placed after VueRouter()
|
||||
Vue(),
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
<br></details>
|
||||
|
||||
<details>
|
||||
<summary>Webpack</summary><br>
|
||||
|
||||
```ts
|
||||
// webpack.config.js
|
||||
module.exports = {
|
||||
/* ... */
|
||||
plugins: [
|
||||
require('unplugin-vue-router/webpack')({
|
||||
/* options */
|
||||
}),
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
<br></details>
|
||||
|
||||
<details>
|
||||
<summary>Vue CLI</summary><br>
|
||||
|
||||
```ts
|
||||
// vue.config.js
|
||||
module.exports = {
|
||||
configureWebpack: {
|
||||
plugins: [
|
||||
require('unplugin-vue-router/webpack')({
|
||||
/* options */
|
||||
}),
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<br></details>
|
||||
|
||||
<details>
|
||||
<summary>esbuild</summary><br>
|
||||
|
||||
```ts
|
||||
// esbuild.config.js
|
||||
import { build } from 'esbuild'
|
||||
import VueRouter from 'unplugin-vue-router/esbuild'
|
||||
|
||||
build({
|
||||
plugins: [VueRouter()],
|
||||
})
|
||||
```
|
||||
|
||||
<br></details>
|
||||
|
||||
## Setup
|
||||
|
||||
After installing, **you should run your dev server** (usually `npm run dev`) **to generate the first version of the types**. Then you need to add the types to your `tsconfig.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"include": [
|
||||
// ...
|
||||
"./typed-router.d.ts"
|
||||
],
|
||||
// ...
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
"moduleResolution": "Bundler"
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, if you have an `env.d.ts` file like the one created by `npm vue create <my-project>`, add the `unplugin-vue-router/client` types to it:
|
||||
|
||||
```ts
|
||||
// env.d.ts
|
||||
/// <reference types="vite/client" />
|
||||
/// <reference types="unplugin-vue-router/client" />
|
||||
```
|
||||
|
||||
If you don't have an `env.d.ts` file, you can create one and add the unplugin-vue-router types to it _or_ you can add them to the `types` property in your `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
"types": ["unplugin-vue-router/client"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally, import the generated routes from `vue-router/auto-routes` and pass them to the router:
|
||||
|
||||
```diff
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
+import { routes } from 'vue-router/auto-routes'
|
||||
|
||||
createRouter({
|
||||
history: createWebHistory(),
|
||||
// pass the generated routes written by the plugin 🤖
|
||||
+ routes,
|
||||
})
|
||||
```
|
||||
|
||||
Alternatively, **you can also import the `routes` array** and create the router manually or pass it to some plugin. Here is an example with [Vitesse starter](https://github.com/antfu-collective/vitesse/blob/main/src/main.ts):
|
||||
|
||||
```diff
|
||||
import { ViteSSG } from 'vite-ssg'
|
||||
import { setupLayouts } from 'virtual:generated-layouts'
|
||||
import App from './App.vue'
|
||||
import type { UserModule } from './types'
|
||||
-import generatedRoutes from '~pages'
|
||||
+import { routes } from 'vue-router/auto-routes'
|
||||
|
||||
import '@unocss/reset/tailwind.css'
|
||||
import './styles/main.css'
|
||||
import 'uno.css'
|
||||
|
||||
-const routes = setupLayouts(generatedRoutes)
|
||||
|
||||
// https://github.com/antfu/vite-ssg
|
||||
export const createApp = ViteSSG(
|
||||
App,
|
||||
{
|
||||
- routes,
|
||||
+ routes: setupLayouts(routes),
|
||||
base: import.meta.env.BASE_URL
|
||||
},
|
||||
(ctx) => {
|
||||
// install all modules under `modules/`
|
||||
Object.values(import.meta.glob<{ install: UserModule }>('./modules/*.ts', { eager: true }))
|
||||
.forEach(i => i.install?.(ctx))
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
- [📖 Check more in the Documentation](https://uvr.esm.is).
|
||||
|
||||
## License
|
||||
|
||||
[MIT](http://opensource.org/licenses/MIT)
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
declare module 'vue-router/auto-routes' {
|
||||
import type { RouteRecordRaw, Router } from 'vue-router'
|
||||
|
||||
/**
|
||||
* Array of routes generated by unplugin-vue-router
|
||||
*/
|
||||
export 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 function handleHotUpdate(
|
||||
router: Router,
|
||||
hotUpdateCallback?: (newRoutes: RouteRecordRaw[]) => void
|
||||
): void
|
||||
}
|
||||
|
||||
declare module 'vue-router' {
|
||||
import type { RouteNamedMap } from 'vue-router/auto-routes'
|
||||
|
||||
export interface TypesConfig {
|
||||
RouteNamedMap: RouteNamedMap
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: remove vue-router/auto in next major
|
||||
|
||||
/**
|
||||
* @deprecated Directly import from 'vue-router' instead
|
||||
*/
|
||||
declare module 'vue-router/auto' {
|
||||
// reexport all types that are not augmented by unplugin-vue-router
|
||||
export * from 'vue-router'
|
||||
|
||||
export { definePage } from 'unplugin-vue-router/runtime'
|
||||
// Experimental Data Fetching
|
||||
export {
|
||||
DataLoaderPlugin,
|
||||
NavigationResult,
|
||||
} from 'unplugin-vue-router/data-loaders'
|
||||
// must be added to the virtual vue-router/auto
|
||||
// FIXME: is there a way to achieve this without losing the types?
|
||||
// export { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic'
|
||||
// export { defineColadaLoader } from 'unplugin-vue-router/data-loaders/pinia-colada'
|
||||
}
|
||||
|
||||
// Make the macros globally available
|
||||
declare global {
|
||||
const definePage: (typeof import('unplugin-vue-router/runtime'))['definePage']
|
||||
}
|
||||
|
||||
export {}
|
||||
Generated
Vendored
+151
@@ -0,0 +1,151 @@
|
||||
const require_createDataLoader = require('./createDataLoader-DPzze8fV.cjs');
|
||||
const vue_router = require_createDataLoader.__toESM(require("vue-router"));
|
||||
const unplugin_vue_router_data_loaders = require_createDataLoader.__toESM(require("unplugin-vue-router/data-loaders"));
|
||||
const vue = require_createDataLoader.__toESM(require("vue"));
|
||||
|
||||
//#region src/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[unplugin_vue_router_data_loaders.LOADER_ENTRIES_KEY];
|
||||
const isSSR = router[unplugin_vue_router_data_loaders.IS_SSR_KEY];
|
||||
if (!entries.has(loader)) entries.set(loader, {
|
||||
data: (0, vue.shallowRef)(),
|
||||
isLoading: (0, vue.shallowRef)(false),
|
||||
error: (0, vue.shallowRef)(),
|
||||
to,
|
||||
options,
|
||||
children: /* @__PURE__ */ new Set(),
|
||||
resetPending() {
|
||||
this.pendingLoad = null;
|
||||
this.pendingTo = null;
|
||||
},
|
||||
pendingLoad: null,
|
||||
pendingTo: null,
|
||||
staged: unplugin_vue_router_data_loaders.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 = unplugin_vue_router_data_loaders.STAGED_NO_VALUE;
|
||||
if (initialRootData && key in initialRootData) {
|
||||
initialData = initialRootData[key];
|
||||
delete initialRootData[key];
|
||||
}
|
||||
if (initialData !== unplugin_vue_router_data_loaders.STAGED_NO_VALUE) {
|
||||
data.value = initialData;
|
||||
return entry.pendingLoad = Promise.resolve();
|
||||
}
|
||||
entry.pendingTo = to;
|
||||
isLoading.value = true;
|
||||
const currentContext = (0, unplugin_vue_router_data_loaders.getCurrentContext)();
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
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/posva/unplugin-vue-router/`);
|
||||
}
|
||||
(0, unplugin_vue_router_data_loaders.setCurrentContext)([
|
||||
entry,
|
||||
router,
|
||||
to
|
||||
]);
|
||||
entry.staged = unplugin_vue_router_data_loaders.STAGED_NO_VALUE;
|
||||
entry.stagedError = error.value;
|
||||
const currentLoad = Promise.resolve(loader(to, { signal: to.meta[unplugin_vue_router_data_loaders.ABORT_CONTROLLER_KEY]?.signal })).then((d) => {
|
||||
if (entry.pendingLoad === currentLoad) if (d instanceof unplugin_vue_router_data_loaders.NavigationResult) to.meta[unplugin_vue_router_data_loaders.NAVIGATION_RESULTS_KEY].push(d);
|
||||
else {
|
||||
entry.staged = d;
|
||||
entry.stagedError = null;
|
||||
}
|
||||
}).catch((e) => {
|
||||
if (entry.pendingLoad === currentLoad) {
|
||||
entry.stagedError = e;
|
||||
if (!require_createDataLoader.toLazyValue(options.lazy, to, from) || isSSR) throw e;
|
||||
}
|
||||
}).finally(() => {
|
||||
(0, unplugin_vue_router_data_loaders.setCurrentContext)(currentContext);
|
||||
if (entry.pendingLoad === currentLoad) {
|
||||
isLoading.value = false;
|
||||
if (options.commit === "immediate" || !router[unplugin_vue_router_data_loaders.PENDING_LOCATION_KEY]) entry.commit(to);
|
||||
}
|
||||
});
|
||||
(0, unplugin_vue_router_data_loaders.setCurrentContext)(currentContext);
|
||||
entry.pendingLoad = currentLoad;
|
||||
return currentLoad;
|
||||
}
|
||||
function commit(to) {
|
||||
if (this.pendingTo === to) {
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
if (this.staged === unplugin_vue_router_data_loaders.STAGED_NO_VALUE) console.warn(`Loader "${options.key}"'s "commit()" was called but there is no staged data.`);
|
||||
}
|
||||
if (this.staged !== unplugin_vue_router_data_loaders.STAGED_NO_VALUE) this.data.value = this.staged;
|
||||
this.error.value = this.stagedError;
|
||||
this.staged = unplugin_vue_router_data_loaders.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 = (0, unplugin_vue_router_data_loaders.getCurrentContext)();
|
||||
const [parentEntry, _router, _route] = currentContext;
|
||||
const router = _router || (0, vue_router.useRouter)();
|
||||
const route = _route || (0, vue_router.useRoute)();
|
||||
const entries = router[unplugin_vue_router_data_loaders.LOADER_ENTRIES_KEY];
|
||||
let entry = entries.get(loader);
|
||||
if (!entry || parentEntry && entry.pendingTo !== route || !entry.pendingLoad) router[unplugin_vue_router_data_loaders.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/posva/unplugin-vue-router/`);
|
||||
parentEntry.children.add(entry);
|
||||
}
|
||||
const { data, error, isLoading } = entry;
|
||||
const useDataLoaderResult = {
|
||||
data,
|
||||
error,
|
||||
isLoading,
|
||||
reload: (to = router.currentRoute.value) => router[unplugin_vue_router_data_loaders.APP_KEY].runWithContext(() => load(to, router)).then(() => entry.commit(to))
|
||||
};
|
||||
const promise = entry.pendingLoad.then(() => {
|
||||
return entry.staged === unplugin_vue_router_data_loaders.STAGED_NO_VALUE ? data.value : entry.staged;
|
||||
}).catch((e) => parentEntry ? Promise.reject(e) : null);
|
||||
(0, unplugin_vue_router_data_loaders.setCurrentContext)(currentContext);
|
||||
return Object.assign(promise, useDataLoaderResult);
|
||||
};
|
||||
useDataLoader[unplugin_vue_router_data_loaders.IS_USE_DATA_LOADER_KEY] = true;
|
||||
useDataLoader._ = {
|
||||
load,
|
||||
options,
|
||||
getEntry(router) {
|
||||
return router[unplugin_vue_router_data_loaders.LOADER_ENTRIES_KEY].get(loader);
|
||||
}
|
||||
};
|
||||
return useDataLoader;
|
||||
}
|
||||
const DEFAULT_DEFINE_LOADER_OPTIONS = {
|
||||
lazy: false,
|
||||
server: true,
|
||||
commit: "after-load"
|
||||
};
|
||||
/**
|
||||
* Symbol used to store the data in the router so it can be retrieved after the initial navigation.
|
||||
* @internal
|
||||
*/
|
||||
const SERVER_INITIAL_DATA_KEY = Symbol();
|
||||
/**
|
||||
* Initial data generated on server and consumed on client.
|
||||
* @internal
|
||||
*/
|
||||
const INITIAL_DATA_KEY = Symbol();
|
||||
|
||||
//#endregion
|
||||
exports.defineBasicLoader = defineBasicLoader;
|
||||
Generated
Vendored
+78
@@ -0,0 +1,78 @@
|
||||
import { DefineDataLoaderOptionsBase_DefinedData, ErrorDefault } from "./createDataLoader-DviHPCj3.cjs";
|
||||
import { RouteLocationNormalizedLoaded, RouteMap } from "vue-router";
|
||||
import { DataLoaderContextBase, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, UseDataLoader } from "unplugin-vue-router/data-loaders";
|
||||
|
||||
//#region src/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 'vue-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> {}
|
||||
//#endregion
|
||||
export { DataLoaderContext, DefineDataLoaderOptions, DefineDataLoaderOptions_DefinedData, DefineDataLoaderOptions_LaxData, UseDataLoaderBasic, UseDataLoaderBasic_DefinedData, UseDataLoaderBasic_LaxData, defineBasicLoader };
|
||||
Generated
Vendored
+78
@@ -0,0 +1,78 @@
|
||||
import { DefineDataLoaderOptionsBase_DefinedData, ErrorDefault } from "./createDataLoader-BOrRPsVs.js";
|
||||
import { RouteLocationNormalizedLoaded, RouteMap } from "vue-router";
|
||||
import { DataLoaderContextBase, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, UseDataLoader } from "unplugin-vue-router/data-loaders";
|
||||
|
||||
//#region src/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 'vue-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> {}
|
||||
//#endregion
|
||||
export { DataLoaderContext, DefineDataLoaderOptions, DefineDataLoaderOptions_DefinedData, DefineDataLoaderOptions_LaxData, UseDataLoaderBasic, UseDataLoaderBasic_DefinedData, UseDataLoaderBasic_LaxData, defineBasicLoader };
|
||||
Generated
Vendored
+151
@@ -0,0 +1,151 @@
|
||||
import { toLazyValue } from "./createDataLoader-BkaFsukJ.js";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ABORT_CONTROLLER_KEY, APP_KEY, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, getCurrentContext, setCurrentContext } from "unplugin-vue-router/data-loaders";
|
||||
import { shallowRef } from "vue";
|
||||
|
||||
//#region src/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(),
|
||||
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 === "development") {
|
||||
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/posva/unplugin-vue-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) to.meta[NAVIGATION_RESULTS_KEY].push(d);
|
||||
else {
|
||||
entry.staged = d;
|
||||
entry.stagedError = null;
|
||||
}
|
||||
}).catch((e) => {
|
||||
if (entry.pendingLoad === currentLoad) {
|
||||
entry.stagedError = e;
|
||||
if (!toLazyValue(options.lazy, to, from) || isSSR) throw e;
|
||||
}
|
||||
}).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 === "development") {
|
||||
if (this.staged === STAGED_NO_VALUE) 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/posva/unplugin-vue-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(() => {
|
||||
return entry.staged === STAGED_NO_VALUE ? data.value : entry.staged;
|
||||
}).catch((e) => parentEntry ? Promise.reject(e) : null);
|
||||
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;
|
||||
}
|
||||
const DEFAULT_DEFINE_LOADER_OPTIONS = {
|
||||
lazy: false,
|
||||
server: true,
|
||||
commit: "after-load"
|
||||
};
|
||||
/**
|
||||
* Symbol used to store the data in the router so it can be retrieved after the initial navigation.
|
||||
* @internal
|
||||
*/
|
||||
const SERVER_INITIAL_DATA_KEY = Symbol();
|
||||
/**
|
||||
* Initial data generated on server and consumed on client.
|
||||
* @internal
|
||||
*/
|
||||
const INITIAL_DATA_KEY = Symbol();
|
||||
|
||||
//#endregion
|
||||
export { defineBasicLoader };
|
||||
Generated
Vendored
+504
@@ -0,0 +1,504 @@
|
||||
import * as vue_router2 from "vue-router";
|
||||
import { LocationQuery, NavigationGuard, NavigationGuardReturn, RouteLocationNormalizedLoaded as RouteLocationNormalizedLoaded$1, Router } from "vue-router";
|
||||
import { App, EffectScope, ShallowRef } from "vue";
|
||||
|
||||
//#region src/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;
|
||||
/**
|
||||
* Gives access to the navigation results when the navigation is aborted by the user within a data loader.
|
||||
* @internal
|
||||
*/
|
||||
declare const NAVIGATION_RESULTS_KEY: unique symbol;
|
||||
/**
|
||||
* Symbol used to save the initial data on the router.
|
||||
* @internal
|
||||
*/
|
||||
declare const IS_SSR_KEY: unique symbol;
|
||||
//#endregion
|
||||
//#region src/utils/index.d.ts
|
||||
/**
|
||||
* Maybe a promise maybe not
|
||||
* @internal
|
||||
*/
|
||||
type _Awaitable<T> = T | PromiseLike<T>;
|
||||
/**
|
||||
* Creates a union type that still allows autocompletion for strings.
|
||||
*@internal
|
||||
*/
|
||||
|
||||
//#endregion
|
||||
//#region src/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>;
|
||||
/**
|
||||
* Possible values to change the result of a navigation within a loader. Can be returned from a data loader and will
|
||||
* appear in `selectNavigationResult`. If thrown, it will immediately cancel the navigation. It can only contain values
|
||||
* that cancel the navigation.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* export const useUserData = defineLoader(async (to) => {
|
||||
* const user = await fetchUser(to.params.id)
|
||||
* if (!user) {
|
||||
* return new NavigationResult('/404')
|
||||
* }
|
||||
* return user
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
declare class NavigationResult {
|
||||
readonly value: _DataLoaderRedirectResult;
|
||||
constructor(value: _DataLoaderRedirectResult);
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* Called if any data loader returns a `NavigationResult` with an array of them. Should decide what is the outcome of
|
||||
* the data fetching guard. Note this isn't called if no data loaders return a `NavigationResult` or if an error is thrown.
|
||||
* @defaultValue `(results) => results[0].value`
|
||||
*/
|
||||
selectNavigationResult?: (results: NavigationResult[]) => _Awaitable<Exclude<NavigationGuardReturn, Function | Promise<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.
|
||||
*/
|
||||
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/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 'vue-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;
|
||||
}
|
||||
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;
|
||||
/**
|
||||
* The navigation results when the navigation is canceled by the user within a data loader.
|
||||
* @internal
|
||||
*/
|
||||
[NAVIGATION_RESULTS_KEY]?: NavigationResult[];
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
//#region src/data-loaders/utils.d.ts
|
||||
/**
|
||||
* @internal: data loaders authoring only. Use `getCurrentContext` instead.
|
||||
*/
|
||||
declare let currentContext: readonly [entry: DataLoaderEntryBase, router: Router, route: RouteLocationNormalizedLoaded$1] | undefined | null;
|
||||
declare function getCurrentContext(): readonly [entry: DataLoaderEntryBase<unknown, unknown, unknown>, router: Router, route: vue_router2.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>;
|
||||
declare const assign: {
|
||||
<T extends {}, U>(target: T, source: U): T & U;
|
||||
<T extends {}, U, V>(target: T, source1: U, source2: V): T & U & V;
|
||||
<T extends {}, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
|
||||
(target: object, ...sources: any[]): any;
|
||||
};
|
||||
/**
|
||||
* Track the reads of a route and its properties
|
||||
* @internal
|
||||
* @param route - route to track
|
||||
*/
|
||||
declare function trackRoute(route: RouteLocationNormalizedLoaded$1): readonly [{
|
||||
readonly hash: string;
|
||||
readonly params: vue_router2.RouteParamsGeneric;
|
||||
readonly query: LocationQuery;
|
||||
readonly matched: vue_router2.RouteLocationMatched[];
|
||||
readonly name: vue_router2.RouteRecordNameGeneric;
|
||||
readonly fullPath: string;
|
||||
readonly redirectedFrom: vue_router2.RouteLocation | undefined;
|
||||
readonly path: string;
|
||||
readonly meta: vue_router2.RouteMeta;
|
||||
}, Partial<vue_router2.RouteParamsGeneric>, Partial<LocationQuery>, {
|
||||
v: string | null;
|
||||
}];
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
declare function isSubsetOf(inner: Partial<LocationQuery>, outer: LocationQuery): boolean;
|
||||
//#endregion
|
||||
//#region src/data-loaders/types-config.d.ts
|
||||
/**
|
||||
* Allows you to extend the default types of the library.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // types-extension.d.ts
|
||||
* import 'unplugin-vue-router/data-loaders'
|
||||
* export {}
|
||||
* declare module 'unplugin-vue-router/data-loaders' {
|
||||
* interface TypesConfig {
|
||||
* Error: MyCustomError
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
interface TypesConfig {}
|
||||
/**
|
||||
* The default error type used.
|
||||
* @internal
|
||||
*/
|
||||
type ErrorDefault = TypesConfig extends Record<'Error', infer E> ? E : Error;
|
||||
//#endregion
|
||||
//#region src/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$1 | 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$1 | 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$1): 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$1, from?: RouteLocationNormalizedLoaded$1) => 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$1, from?: RouteLocationNormalizedLoaded$1) => 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$1, router: Router, from?: RouteLocationNormalizedLoaded$1, 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$1): Promise<void>;
|
||||
}
|
||||
/**
|
||||
* Loader function that can be passed to `defineLoader()`.
|
||||
*/
|
||||
interface DefineLoaderFn<Data, Context extends DataLoaderContextBase = DataLoaderContextBase, Route = RouteLocationNormalizedLoaded$1> {
|
||||
(route: Route, context: Context): Promise<Data>;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `DefineDataLoaderOptionsBase_LaxData` instead.
|
||||
*/
|
||||
type DefineDataLoaderOptionsBase = DefineDataLoaderOptionsBase_LaxData;
|
||||
//#endregion
|
||||
export { ABORT_CONTROLLER_KEY, APP_KEY, DataLoaderContextBase, DataLoaderEntryBase, DataLoaderPlugin, DataLoaderPluginOptions, DefineDataLoaderOptionsBase, DefineDataLoaderOptionsBase_DefinedData, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, ErrorDefault, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, SetupLoaderGuardOptions, TypesConfig, UseDataLoader, UseDataLoaderInternals, UseDataLoaderResult, _DataLoaderRedirectResult, _DefineLoaderEntryMap, _PromiseMerged, assign, currentContext, getCurrentContext, isSubsetOf, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext };
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
//#region src/data-loaders/createDataLoader.ts
|
||||
const toLazyValue = (lazy, to, from) => typeof lazy === "function" ? lazy(to, from) : lazy;
|
||||
|
||||
//#endregion
|
||||
export { toLazyValue };
|
||||
Generated
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
//#region rolldown:runtime
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
||||
key = keys[i];
|
||||
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
||||
get: ((k) => from[k]).bind(null, key),
|
||||
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
||||
});
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
||||
value: mod,
|
||||
enumerable: true
|
||||
}) : target, mod));
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region src/data-loaders/createDataLoader.ts
|
||||
const toLazyValue = (lazy, to, from) => typeof lazy === "function" ? lazy(to, from) : lazy;
|
||||
|
||||
//#endregion
|
||||
Object.defineProperty(exports, '__toESM', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return __toESM;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'toLazyValue', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return toLazyValue;
|
||||
}
|
||||
});
|
||||
Generated
Vendored
+504
@@ -0,0 +1,504 @@
|
||||
import * as vue_router1 from "vue-router";
|
||||
import { LocationQuery, NavigationGuard, NavigationGuardReturn, RouteLocationNormalizedLoaded as RouteLocationNormalizedLoaded$1, Router } from "vue-router";
|
||||
import { App, EffectScope, ShallowRef } from "vue";
|
||||
|
||||
//#region src/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;
|
||||
/**
|
||||
* Gives access to the navigation results when the navigation is aborted by the user within a data loader.
|
||||
* @internal
|
||||
*/
|
||||
declare const NAVIGATION_RESULTS_KEY: unique symbol;
|
||||
/**
|
||||
* Symbol used to save the initial data on the router.
|
||||
* @internal
|
||||
*/
|
||||
declare const IS_SSR_KEY: unique symbol;
|
||||
//#endregion
|
||||
//#region src/utils/index.d.ts
|
||||
/**
|
||||
* Maybe a promise maybe not
|
||||
* @internal
|
||||
*/
|
||||
type _Awaitable<T> = T | PromiseLike<T>;
|
||||
/**
|
||||
* Creates a union type that still allows autocompletion for strings.
|
||||
*@internal
|
||||
*/
|
||||
|
||||
//#endregion
|
||||
//#region src/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>;
|
||||
/**
|
||||
* Possible values to change the result of a navigation within a loader. Can be returned from a data loader and will
|
||||
* appear in `selectNavigationResult`. If thrown, it will immediately cancel the navigation. It can only contain values
|
||||
* that cancel the navigation.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* export const useUserData = defineLoader(async (to) => {
|
||||
* const user = await fetchUser(to.params.id)
|
||||
* if (!user) {
|
||||
* return new NavigationResult('/404')
|
||||
* }
|
||||
* return user
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
declare class NavigationResult {
|
||||
readonly value: _DataLoaderRedirectResult;
|
||||
constructor(value: _DataLoaderRedirectResult);
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* Called if any data loader returns a `NavigationResult` with an array of them. Should decide what is the outcome of
|
||||
* the data fetching guard. Note this isn't called if no data loaders return a `NavigationResult` or if an error is thrown.
|
||||
* @defaultValue `(results) => results[0].value`
|
||||
*/
|
||||
selectNavigationResult?: (results: NavigationResult[]) => _Awaitable<Exclude<NavigationGuardReturn, Function | Promise<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.
|
||||
*/
|
||||
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/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 'vue-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;
|
||||
}
|
||||
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;
|
||||
/**
|
||||
* The navigation results when the navigation is canceled by the user within a data loader.
|
||||
* @internal
|
||||
*/
|
||||
[NAVIGATION_RESULTS_KEY]?: NavigationResult[];
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
//#region src/data-loaders/utils.d.ts
|
||||
/**
|
||||
* @internal: data loaders authoring only. Use `getCurrentContext` instead.
|
||||
*/
|
||||
declare let currentContext: readonly [entry: DataLoaderEntryBase, router: Router, route: RouteLocationNormalizedLoaded$1] | undefined | null;
|
||||
declare function getCurrentContext(): readonly [entry: DataLoaderEntryBase<unknown, unknown, unknown>, router: Router, route: vue_router1.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>;
|
||||
declare const assign: {
|
||||
<T extends {}, U>(target: T, source: U): T & U;
|
||||
<T extends {}, U, V>(target: T, source1: U, source2: V): T & U & V;
|
||||
<T extends {}, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
|
||||
(target: object, ...sources: any[]): any;
|
||||
};
|
||||
/**
|
||||
* Track the reads of a route and its properties
|
||||
* @internal
|
||||
* @param route - route to track
|
||||
*/
|
||||
declare function trackRoute(route: RouteLocationNormalizedLoaded$1): readonly [{
|
||||
readonly hash: string;
|
||||
readonly params: vue_router1.RouteParamsGeneric;
|
||||
readonly query: LocationQuery;
|
||||
readonly matched: vue_router1.RouteLocationMatched[];
|
||||
readonly name: vue_router1.RouteRecordNameGeneric;
|
||||
readonly fullPath: string;
|
||||
readonly redirectedFrom: vue_router1.RouteLocation | undefined;
|
||||
readonly path: string;
|
||||
readonly meta: vue_router1.RouteMeta;
|
||||
}, Partial<vue_router1.RouteParamsGeneric>, Partial<LocationQuery>, {
|
||||
v: string | null;
|
||||
}];
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
declare function isSubsetOf(inner: Partial<LocationQuery>, outer: LocationQuery): boolean;
|
||||
//#endregion
|
||||
//#region src/data-loaders/types-config.d.ts
|
||||
/**
|
||||
* Allows you to extend the default types of the library.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // types-extension.d.ts
|
||||
* import 'unplugin-vue-router/data-loaders'
|
||||
* export {}
|
||||
* declare module 'unplugin-vue-router/data-loaders' {
|
||||
* interface TypesConfig {
|
||||
* Error: MyCustomError
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
interface TypesConfig {}
|
||||
/**
|
||||
* The default error type used.
|
||||
* @internal
|
||||
*/
|
||||
type ErrorDefault = TypesConfig extends Record<'Error', infer E> ? E : Error;
|
||||
//#endregion
|
||||
//#region src/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$1 | 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$1 | 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$1): 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$1, from?: RouteLocationNormalizedLoaded$1) => 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$1, from?: RouteLocationNormalizedLoaded$1) => 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$1, router: Router, from?: RouteLocationNormalizedLoaded$1, 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$1): Promise<void>;
|
||||
}
|
||||
/**
|
||||
* Loader function that can be passed to `defineLoader()`.
|
||||
*/
|
||||
interface DefineLoaderFn<Data, Context extends DataLoaderContextBase = DataLoaderContextBase, Route = RouteLocationNormalizedLoaded$1> {
|
||||
(route: Route, context: Context): Promise<Data>;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `DefineDataLoaderOptionsBase_LaxData` instead.
|
||||
*/
|
||||
type DefineDataLoaderOptionsBase = DefineDataLoaderOptionsBase_LaxData;
|
||||
//#endregion
|
||||
export { ABORT_CONTROLLER_KEY, APP_KEY, DataLoaderContextBase, DataLoaderEntryBase, DataLoaderPlugin, DataLoaderPluginOptions, DefineDataLoaderOptionsBase, DefineDataLoaderOptionsBase_DefinedData, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, ErrorDefault, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, SetupLoaderGuardOptions, TypesConfig, UseDataLoader, UseDataLoaderInternals, UseDataLoaderResult, _DataLoaderRedirectResult, _DefineLoaderEntryMap, _PromiseMerged, assign, currentContext, getCurrentContext, isSubsetOf, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext };
|
||||
Generated
Vendored
+204
@@ -0,0 +1,204 @@
|
||||
const require_createDataLoader = require('./createDataLoader-DPzze8fV.cjs');
|
||||
const require_utils = require('./utils-vwCPb_Ef.cjs');
|
||||
const vue_router = require_createDataLoader.__toESM(require("vue-router"));
|
||||
const vue = require_createDataLoader.__toESM(require("vue"));
|
||||
|
||||
//#region src/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 = [], selectNavigationResult = (results) => results[0].value }) {
|
||||
if (router[require_utils.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[require_utils.LOADER_ENTRIES_KEY] = /* @__PURE__ */ new WeakMap();
|
||||
router[require_utils.APP_KEY] = app;
|
||||
router[require_utils.IS_SSR_KEY] = !!isSSR;
|
||||
const isDataLoading = scope.run(() => (0, vue.shallowRef)(false));
|
||||
app.provide(IS_DATA_LOADING_KEY, isDataLoading);
|
||||
const removeLoaderGuard = router.beforeEach((to) => {
|
||||
if (router[require_utils.PENDING_LOCATION_KEY]) router[require_utils.PENDING_LOCATION_KEY].meta[require_utils.ABORT_CONTROLLER_KEY]?.abort();
|
||||
router[require_utils.PENDING_LOCATION_KEY] = to;
|
||||
to.meta[require_utils.LOADER_SET_KEY] = /* @__PURE__ */ new Set();
|
||||
to.meta[require_utils.ABORT_CONTROLLER_KEY] = new AbortController();
|
||||
to.meta[require_utils.NAVIGATION_RESULTS_KEY] = [];
|
||||
const lazyLoadingPromises = [];
|
||||
for (const record of to.matched) if (!record.meta[require_utils.LOADER_SET_KEY]) {
|
||||
record.meta[require_utils.LOADER_SET_KEY] = new Set(record.meta.loaders || []);
|
||||
for (const componentName in record.components) {
|
||||
const component = record.components[componentName];
|
||||
const promise = (isAsyncModule(component) ? component() : Promise.resolve(component)).then((viewModule) => {
|
||||
if (typeof viewModule === "function") return;
|
||||
for (const exportName in viewModule) {
|
||||
const exportValue = viewModule[exportName];
|
||||
if (require_utils.isDataLoader(exportValue)) record.meta[require_utils.LOADER_SET_KEY].add(exportValue);
|
||||
}
|
||||
if (Array.isArray(viewModule.__loaders)) {
|
||||
for (const loader of viewModule.__loaders) if (require_utils.isDataLoader(loader)) record.meta[require_utils.LOADER_SET_KEY].add(loader);
|
||||
}
|
||||
});
|
||||
lazyLoadingPromises.push(promise);
|
||||
}
|
||||
}
|
||||
return Promise.all(lazyLoadingPromises).then(() => {
|
||||
for (const record of to.matched) for (const loader of record.meta[require_utils.LOADER_SET_KEY]) to.meta[require_utils.LOADER_SET_KEY].add(loader);
|
||||
});
|
||||
});
|
||||
const removeDataLoaderGuard = router.beforeResolve((to, from) => {
|
||||
const loaders = Array.from(to.meta[require_utils.LOADER_SET_KEY]);
|
||||
require_utils.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 && require_createDataLoader.toLazyValue(lazy, to, from) ? void 0 : ret.catch((reason) => {
|
||||
if (!errors) throw reason;
|
||||
if (errors === true) {
|
||||
if (Array.isArray(globalErrors) ? globalErrors.some((Err) => reason instanceof Err) : globalErrors(reason)) return;
|
||||
} else if (Array.isArray(errors) ? errors.some((Err) => reason instanceof Err) : errors(reason)) return;
|
||||
throw reason;
|
||||
});
|
||||
})).then(() => {
|
||||
if (to.meta[require_utils.NAVIGATION_RESULTS_KEY].length) return selectNavigationResult(to.meta[require_utils.NAVIGATION_RESULTS_KEY]);
|
||||
}).catch((error) => error instanceof NavigationResult ? error.value : Promise.reject(error)).finally(() => {
|
||||
require_utils.setCurrentContext([]);
|
||||
isDataLoading.value = false;
|
||||
});
|
||||
});
|
||||
const removeAfterEach = router.afterEach((to, from, failure) => {
|
||||
if (failure) {
|
||||
to.meta[require_utils.ABORT_CONTROLLER_KEY]?.abort(failure);
|
||||
if ((0, vue_router.isNavigationFailure)(failure, 16)) for (const loader of to.meta[require_utils.LOADER_SET_KEY]) {
|
||||
const entry = loader._.getEntry(router);
|
||||
entry.resetPending();
|
||||
}
|
||||
} else for (const loader of to.meta[require_utils.LOADER_SET_KEY]) {
|
||||
const { commit, lazy } = loader._.options;
|
||||
if (commit === "after-load") {
|
||||
const entry = loader._.getEntry(router);
|
||||
if (entry && (!require_createDataLoader.toLazyValue(lazy, to, from) || !entry.isLoading.value)) entry.commit(to);
|
||||
}
|
||||
}
|
||||
if (router[require_utils.PENDING_LOCATION_KEY] === to) router[require_utils.PENDING_LOCATION_KEY] = null;
|
||||
});
|
||||
const removeOnError = router.onError((error, to) => {
|
||||
to.meta[require_utils.ABORT_CONTROLLER_KEY]?.abort(error);
|
||||
if (router[require_utils.PENDING_LOCATION_KEY] === to) router[require_utils.PENDING_LOCATION_KEY] = null;
|
||||
});
|
||||
return () => {
|
||||
delete router[require_utils.LOADER_ENTRIES_KEY];
|
||||
delete router[require_utils.APP_KEY];
|
||||
removeLoaderGuard();
|
||||
removeDataLoaderGuard();
|
||||
removeAfterEach();
|
||||
removeOnError();
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Allows differentiating lazy components from functional components and vue-class-component
|
||||
* @internal
|
||||
*
|
||||
* @param component
|
||||
*/
|
||||
function isAsyncModule(asyncMod) {
|
||||
return typeof asyncMod === "function" && !("displayName" in asyncMod) && !("props" in asyncMod) && !("emits" in asyncMod) && !("__vccOpts" in asyncMod);
|
||||
}
|
||||
/**
|
||||
* Possible values to change the result of a navigation within a loader. Can be returned from a data loader and will
|
||||
* appear in `selectNavigationResult`. If thrown, it will immediately cancel the navigation. It can only contain values
|
||||
* that cancel the navigation.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* export const useUserData = defineLoader(async (to) => {
|
||||
* const user = await fetchUser(to.params.id)
|
||||
* if (!user) {
|
||||
* return new NavigationResult('/404')
|
||||
* }
|
||||
* return user
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
var NavigationResult = class {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 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 = (0, vue.effectScope)(true);
|
||||
const removeGuards = setupLoaderGuard(require_utils.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 (0, vue.inject)(IS_DATA_LOADING_KEY);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
exports.ABORT_CONTROLLER_KEY = require_utils.ABORT_CONTROLLER_KEY;
|
||||
exports.APP_KEY = require_utils.APP_KEY;
|
||||
exports.DataLoaderPlugin = DataLoaderPlugin;
|
||||
exports.IS_SSR_KEY = require_utils.IS_SSR_KEY;
|
||||
exports.IS_USE_DATA_LOADER_KEY = require_utils.IS_USE_DATA_LOADER_KEY;
|
||||
exports.LOADER_ENTRIES_KEY = require_utils.LOADER_ENTRIES_KEY;
|
||||
exports.LOADER_SET_KEY = require_utils.LOADER_SET_KEY;
|
||||
exports.NAVIGATION_RESULTS_KEY = require_utils.NAVIGATION_RESULTS_KEY;
|
||||
exports.NavigationResult = NavigationResult;
|
||||
exports.PENDING_LOCATION_KEY = require_utils.PENDING_LOCATION_KEY;
|
||||
exports.STAGED_NO_VALUE = require_utils.STAGED_NO_VALUE;
|
||||
exports.assign = require_utils.assign;
|
||||
Object.defineProperty(exports, 'currentContext', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return require_utils.currentContext;
|
||||
}
|
||||
});
|
||||
exports.getCurrentContext = require_utils.getCurrentContext;
|
||||
exports.isSubsetOf = require_utils.isSubsetOf;
|
||||
exports.setCurrentContext = require_utils.setCurrentContext;
|
||||
exports.toLazyValue = require_createDataLoader.toLazyValue;
|
||||
exports.trackRoute = require_utils.trackRoute;
|
||||
exports.useIsDataLoading = useIsDataLoading;
|
||||
exports.withLoaderContext = require_utils.withLoaderContext;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import { ABORT_CONTROLLER_KEY, APP_KEY, DataLoaderContextBase, DataLoaderEntryBase, DataLoaderPlugin, DataLoaderPluginOptions, DefineDataLoaderOptionsBase, DefineDataLoaderOptionsBase_DefinedData, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, ErrorDefault, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, SetupLoaderGuardOptions, TypesConfig, UseDataLoader, UseDataLoaderInternals, UseDataLoaderResult, _DataLoaderRedirectResult, _DefineLoaderEntryMap, _PromiseMerged, assign, currentContext, getCurrentContext, isSubsetOf, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext } from "./createDataLoader-DviHPCj3.cjs";
|
||||
export { ABORT_CONTROLLER_KEY, APP_KEY, DataLoaderContextBase, DataLoaderEntryBase, DataLoaderPlugin, DataLoaderPluginOptions, DefineDataLoaderOptionsBase, DefineDataLoaderOptionsBase_DefinedData, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, ErrorDefault, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, SetupLoaderGuardOptions, TypesConfig, UseDataLoader, UseDataLoaderInternals, UseDataLoaderResult, _DataLoaderRedirectResult, _DefineLoaderEntryMap, _PromiseMerged, assign, currentContext, getCurrentContext, isSubsetOf, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext };
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import { ABORT_CONTROLLER_KEY, APP_KEY, DataLoaderContextBase, DataLoaderEntryBase, DataLoaderPlugin, DataLoaderPluginOptions, DefineDataLoaderOptionsBase, DefineDataLoaderOptionsBase_DefinedData, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, ErrorDefault, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, SetupLoaderGuardOptions, TypesConfig, UseDataLoader, UseDataLoaderInternals, UseDataLoaderResult, _DataLoaderRedirectResult, _DefineLoaderEntryMap, _PromiseMerged, assign, currentContext, getCurrentContext, isSubsetOf, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext } from "./createDataLoader-BOrRPsVs.js";
|
||||
export { ABORT_CONTROLLER_KEY, APP_KEY, DataLoaderContextBase, DataLoaderEntryBase, DataLoaderPlugin, DataLoaderPluginOptions, DefineDataLoaderOptionsBase, DefineDataLoaderOptionsBase_DefinedData, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, ErrorDefault, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, SetupLoaderGuardOptions, TypesConfig, UseDataLoader, UseDataLoaderInternals, UseDataLoaderResult, _DataLoaderRedirectResult, _DefineLoaderEntryMap, _PromiseMerged, assign, currentContext, getCurrentContext, isSubsetOf, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext };
|
||||
Generated
Vendored
+180
@@ -0,0 +1,180 @@
|
||||
import { toLazyValue } from "./createDataLoader-BkaFsukJ.js";
|
||||
import { ABORT_CONTROLLER_KEY, APP_KEY, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, PENDING_LOCATION_KEY, STAGED_NO_VALUE, assign, currentContext, getCurrentContext, isDataLoader, isSubsetOf, setCurrentContext, trackRoute, withLoaderContext } from "./utils-D_yE8zIx.js";
|
||||
import { isNavigationFailure } from "vue-router";
|
||||
import { effectScope, inject, shallowRef } from "vue";
|
||||
|
||||
//#region src/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 = [], selectNavigationResult = (results) => results[0].value }) {
|
||||
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[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();
|
||||
to.meta[NAVIGATION_RESULTS_KEY] = [];
|
||||
const lazyLoadingPromises = [];
|
||||
for (const record of to.matched) if (!record.meta[LOADER_SET_KEY]) {
|
||||
record.meta[LOADER_SET_KEY] = new Set(record.meta.loaders || []);
|
||||
for (const componentName in record.components) {
|
||||
const component = record.components[componentName];
|
||||
const promise = (isAsyncModule(component) ? component() : Promise.resolve(component)).then((viewModule) => {
|
||||
if (typeof viewModule === "function") return;
|
||||
for (const exportName in viewModule) {
|
||||
const exportValue = viewModule[exportName];
|
||||
if (isDataLoader(exportValue)) record.meta[LOADER_SET_KEY].add(exportValue);
|
||||
}
|
||||
if (Array.isArray(viewModule.__loaders)) {
|
||||
for (const loader of viewModule.__loaders) if (isDataLoader(loader)) record.meta[LOADER_SET_KEY].add(loader);
|
||||
}
|
||||
});
|
||||
lazyLoadingPromises.push(promise);
|
||||
}
|
||||
}
|
||||
return Promise.all(lazyLoadingPromises).then(() => {
|
||||
for (const record of to.matched) for (const loader of record.meta[LOADER_SET_KEY]) to.meta[LOADER_SET_KEY].add(loader);
|
||||
});
|
||||
});
|
||||
const removeDataLoaderGuard = router.beforeResolve((to, from) => {
|
||||
const loaders = Array.from(to.meta[LOADER_SET_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) throw reason;
|
||||
if (errors === true) {
|
||||
if (Array.isArray(globalErrors) ? globalErrors.some((Err) => reason instanceof Err) : globalErrors(reason)) return;
|
||||
} else if (Array.isArray(errors) ? errors.some((Err) => reason instanceof Err) : errors(reason)) return;
|
||||
throw reason;
|
||||
});
|
||||
})).then(() => {
|
||||
if (to.meta[NAVIGATION_RESULTS_KEY].length) return selectNavigationResult(to.meta[NAVIGATION_RESULTS_KEY]);
|
||||
}).catch((error) => error instanceof NavigationResult ? error.value : 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, 16)) for (const loader of to.meta[LOADER_SET_KEY]) {
|
||||
const entry = loader._.getEntry(router);
|
||||
entry.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 differentiating lazy components from functional components and vue-class-component
|
||||
* @internal
|
||||
*
|
||||
* @param component
|
||||
*/
|
||||
function isAsyncModule(asyncMod) {
|
||||
return typeof asyncMod === "function" && !("displayName" in asyncMod) && !("props" in asyncMod) && !("emits" in asyncMod) && !("__vccOpts" in asyncMod);
|
||||
}
|
||||
/**
|
||||
* Possible values to change the result of a navigation within a loader. Can be returned from a data loader and will
|
||||
* appear in `selectNavigationResult`. If thrown, it will immediately cancel the navigation. It can only contain values
|
||||
* that cancel the navigation.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* export const useUserData = defineLoader(async (to) => {
|
||||
* const user = await fetchUser(to.params.id)
|
||||
* if (!user) {
|
||||
* return new NavigationResult('/404')
|
||||
* }
|
||||
* return user
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
var NavigationResult = class {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 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 { ABORT_CONTROLLER_KEY, APP_KEY, DataLoaderPlugin, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, assign, currentContext, getCurrentContext, isSubsetOf, setCurrentContext, toLazyValue, trackRoute, useIsDataLoading, withLoaderContext };
|
||||
Generated
Vendored
+220
@@ -0,0 +1,220 @@
|
||||
const require_createDataLoader = require('./createDataLoader-DPzze8fV.cjs');
|
||||
require('./utils-vwCPb_Ef.cjs');
|
||||
const vue_router = require_createDataLoader.__toESM(require("vue-router"));
|
||||
const unplugin_vue_router_data_loaders = require_createDataLoader.__toESM(require("unplugin-vue-router/data-loaders"));
|
||||
const vue = require_createDataLoader.__toESM(require("vue"));
|
||||
const __pinia_colada = require_createDataLoader.__toESM(require("@pinia/colada"));
|
||||
|
||||
//#region src/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;
|
||||
function load(to, router, from, parent, reload) {
|
||||
const entries = router[unplugin_vue_router_data_loaders.LOADER_ENTRIES_KEY];
|
||||
const isSSR = router[unplugin_vue_router_data_loaders.IS_SSR_KEY];
|
||||
const key = serializeQueryKey(options.key, to);
|
||||
if (!entries.has(loader)) {
|
||||
const route = (0, vue.shallowRef)(to);
|
||||
entries.set(loader, {
|
||||
data: (0, vue.shallowRef)(),
|
||||
isLoading: (0, vue.shallowRef)(false),
|
||||
error: (0, vue.shallowRef)(),
|
||||
to,
|
||||
options,
|
||||
children: /* @__PURE__ */ new Set(),
|
||||
resetPending() {
|
||||
this.pendingTo = null;
|
||||
this.pendingLoad = null;
|
||||
this.isLoading.value = false;
|
||||
},
|
||||
staged: unplugin_vue_router_data_loaders.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 = (0, unplugin_vue_router_data_loaders.getCurrentContext)();
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
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/posva/unplugin-vue-router/`);
|
||||
}
|
||||
(0, unplugin_vue_router_data_loaders.setCurrentContext)([
|
||||
entry,
|
||||
router,
|
||||
to
|
||||
]);
|
||||
const app = router[unplugin_vue_router_data_loaders.APP_KEY];
|
||||
if (!entry.ext) {
|
||||
entry.ext = (0, __pinia_colada.useQuery)({
|
||||
...options,
|
||||
query: () => {
|
||||
const route = entry.route.value;
|
||||
const [trackedRoute, params, query, hash] = (0, unplugin_vue_router_data_loaders.trackRoute)(route);
|
||||
entry.tracked.set(joinKeys(serializeQueryKey(options.key, trackedRoute)), {
|
||||
ready: false,
|
||||
params,
|
||||
query,
|
||||
hash
|
||||
});
|
||||
return app.runWithContext(() => loader(trackedRoute, { signal: route.meta[unplugin_vue_router_data_loaders.ABORT_CONTROLLER_KEY]?.signal }));
|
||||
},
|
||||
key: () => toValueWithParameters(options.key, entry.route.value)
|
||||
});
|
||||
if (entry.ext.asyncStatus.value === "loading") reload = false;
|
||||
}
|
||||
const { isLoading, data, error, ext } = entry;
|
||||
if (isInitial) {
|
||||
isInitial = false;
|
||||
if (ext.data.value !== void 0) {
|
||||
data.value = ext.data.value;
|
||||
(0, unplugin_vue_router_data_loaders.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 = unplugin_vue_router_data_loaders.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) {
|
||||
entry.stagedError = newError;
|
||||
if (!require_createDataLoader.toLazyValue(options.lazy, to, from) || isSSR) throw newError;
|
||||
} else {
|
||||
const newData = ext.data.value;
|
||||
if (newData instanceof unplugin_vue_router_data_loaders.NavigationResult) to.meta[unplugin_vue_router_data_loaders.NAVIGATION_RESULTS_KEY].push(newData);
|
||||
else {
|
||||
entry.staged = newData;
|
||||
entry.stagedError = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
(0, unplugin_vue_router_data_loaders.setCurrentContext)(currentContext);
|
||||
if (entry.pendingLoad === currentLoad) {
|
||||
isLoading.value = false;
|
||||
if (options.commit === "immediate" || !router[unplugin_vue_router_data_loaders.PENDING_LOCATION_KEY]) entry.commit(to);
|
||||
}
|
||||
});
|
||||
(0, unplugin_vue_router_data_loaders.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 === "development") {
|
||||
if (this.staged === unplugin_vue_router_data_loaders.STAGED_NO_VALUE) console.warn(`Loader "${key}"'s "commit()" was called but there is no staged data.`);
|
||||
}
|
||||
if (this.staged !== unplugin_vue_router_data_loaders.STAGED_NO_VALUE) {
|
||||
this.data.value = this.staged;
|
||||
if (process.env.NODE_ENV === "development" && !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 = unplugin_vue_router_data_loaders.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 currentEntry = (0, unplugin_vue_router_data_loaders.getCurrentContext)();
|
||||
const [parentEntry, _router, _route] = currentEntry;
|
||||
const router = _router || (0, vue_router.useRouter)();
|
||||
const route = _route || (0, vue_router.useRoute)();
|
||||
const app = router[unplugin_vue_router_data_loaders.APP_KEY];
|
||||
const entries = router[unplugin_vue_router_data_loaders.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, ext } = entry;
|
||||
(0, vue.watch)(ext.data, (newData) => {
|
||||
if (!router[unplugin_vue_router_data_loaders.PENDING_LOCATION_KEY]) data.value = newData;
|
||||
});
|
||||
(0, vue.watch)(ext.isLoading, (isFetching) => {
|
||||
if (!router[unplugin_vue_router_data_loaders.PENDING_LOCATION_KEY]) isLoading.value = isFetching;
|
||||
});
|
||||
(0, vue.watch)(ext.error, (newError) => {
|
||||
if (!router[unplugin_vue_router_data_loaders.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(() => {
|
||||
return entry.staged === unplugin_vue_router_data_loaders.STAGED_NO_VALUE ? ext.data.value : entry.staged;
|
||||
}).catch((e) => parentEntry ? Promise.reject(e) : null);
|
||||
(0, unplugin_vue_router_data_loaders.setCurrentContext)(currentEntry);
|
||||
return (0, unplugin_vue_router_data_loaders.assign)(promise, useDataLoaderResult);
|
||||
};
|
||||
useDataLoader[unplugin_vue_router_data_loaders.IS_USE_DATA_LOADER_KEY] = true;
|
||||
useDataLoader._ = {
|
||||
load,
|
||||
options,
|
||||
getEntry(router) {
|
||||
return router[unplugin_vue_router_data_loaders.LOADER_ENTRIES_KEY].get(loader);
|
||||
}
|
||||
};
|
||||
return useDataLoader;
|
||||
}
|
||||
const joinKeys = (keys) => keys.join("|");
|
||||
function hasRouteChanged(to, tracked) {
|
||||
return !tracked.ready || !(0, unplugin_vue_router_data_loaders.isSubsetOf)(tracked.params, to.params) || !(0, unplugin_vue_router_data_loaders.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);
|
||||
const keys = Array.isArray(key) ? key : [key];
|
||||
return keys.map(stringifyFlatObject);
|
||||
}
|
||||
function stringifyFlatObject(obj) {
|
||||
return obj && typeof obj === "object" ? JSON.stringify(obj, Object.keys(obj).sort()) : String(obj);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
exports.defineColadaLoader = defineColadaLoader;
|
||||
Generated
Vendored
+150
@@ -0,0 +1,150 @@
|
||||
import { DefineDataLoaderOptionsBase_DefinedData } from "./createDataLoader-DviHPCj3.cjs";
|
||||
import { LocationQuery, RouteLocationNormalizedLoaded, RouteMap } from "vue-router";
|
||||
import { DataLoaderContextBase, DataLoaderEntryBase, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, ErrorDefault, NavigationResult, UseDataLoader, UseDataLoaderResult, _PromiseMerged } from "unplugin-vue-router/data-loaders";
|
||||
import { ShallowRef } from "vue";
|
||||
import { EntryKey, UseQueryOptions, UseQueryReturn } from "@pinia/colada";
|
||||
|
||||
//#region src/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 { DataColadaLoaderContext, DataLoaderColadaEntry, DefineDataColadaLoaderOptions, DefineDataColadaLoaderOptions_LaxData, UseDataLoaderColadaResult, UseDataLoaderColada_DefinedData, UseDataLoaderColada_LaxData, defineColadaLoader };
|
||||
examples/nuxt3-websocket-client/node_modules/unplugin-vue-router/dist/data-loaders/pinia-colada.d.ts
Generated
Vendored
+150
@@ -0,0 +1,150 @@
|
||||
import { DefineDataLoaderOptionsBase_DefinedData } from "./createDataLoader-BOrRPsVs.js";
|
||||
import { LocationQuery, RouteLocationNormalizedLoaded, RouteMap } from "vue-router";
|
||||
import { DataLoaderContextBase, DataLoaderEntryBase, DefineDataLoaderOptionsBase_LaxData, DefineLoaderFn, ErrorDefault, NavigationResult, UseDataLoader, UseDataLoaderResult, _PromiseMerged } from "unplugin-vue-router/data-loaders";
|
||||
import { ShallowRef } from "vue";
|
||||
import { EntryKey, UseQueryOptions, UseQueryReturn } from "@pinia/colada";
|
||||
|
||||
//#region src/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 { DataColadaLoaderContext, DataLoaderColadaEntry, DefineDataColadaLoaderOptions, DefineDataColadaLoaderOptions_LaxData, UseDataLoaderColadaResult, UseDataLoaderColada_DefinedData, UseDataLoaderColada_LaxData, defineColadaLoader };
|
||||
Generated
Vendored
+220
@@ -0,0 +1,220 @@
|
||||
import { toLazyValue } from "./createDataLoader-BkaFsukJ.js";
|
||||
import "./utils-D_yE8zIx.js";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ABORT_CONTROLLER_KEY, APP_KEY, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, NAVIGATION_RESULTS_KEY, NavigationResult, PENDING_LOCATION_KEY, STAGED_NO_VALUE, assign, getCurrentContext, isSubsetOf, setCurrentContext, trackRoute } from "unplugin-vue-router/data-loaders";
|
||||
import { shallowRef, watch } from "vue";
|
||||
import { useQuery } from "@pinia/colada";
|
||||
|
||||
//#region src/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;
|
||||
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(),
|
||||
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 === "development") {
|
||||
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/posva/unplugin-vue-router/`);
|
||||
}
|
||||
setCurrentContext([
|
||||
entry,
|
||||
router,
|
||||
to
|
||||
]);
|
||||
const app = router[APP_KEY];
|
||||
if (!entry.ext) {
|
||||
entry.ext = 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 app.runWithContext(() => loader(trackedRoute, { signal: route.meta[ABORT_CONTROLLER_KEY]?.signal }));
|
||||
},
|
||||
key: () => toValueWithParameters(options.key, entry.route.value)
|
||||
});
|
||||
if (entry.ext.asyncStatus.value === "loading") 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) {
|
||||
entry.stagedError = newError;
|
||||
if (!toLazyValue(options.lazy, to, from) || isSSR) throw newError;
|
||||
} else {
|
||||
const newData = ext.data.value;
|
||||
if (newData instanceof NavigationResult) to.meta[NAVIGATION_RESULTS_KEY].push(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 === "development") {
|
||||
if (this.staged === STAGED_NO_VALUE) 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 === "development" && !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 currentEntry = getCurrentContext();
|
||||
const [parentEntry, _router, _route] = currentEntry;
|
||||
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, ext } = entry;
|
||||
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(() => {
|
||||
return entry.staged === STAGED_NO_VALUE ? ext.data.value : entry.staged;
|
||||
}).catch((e) => parentEntry ? Promise.reject(e) : null);
|
||||
setCurrentContext(currentEntry);
|
||||
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);
|
||||
const keys = Array.isArray(key) ? key : [key];
|
||||
return keys.map(stringifyFlatObject);
|
||||
}
|
||||
function stringifyFlatObject(obj) {
|
||||
return obj && typeof obj === "object" ? JSON.stringify(obj, Object.keys(obj).sort()) : String(obj);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
export { defineColadaLoader };
|
||||
examples/nuxt3-websocket-client/node_modules/unplugin-vue-router/dist/data-loaders/utils-D_yE8zIx.js
Generated
Vendored
+142
@@ -0,0 +1,142 @@
|
||||
//#region src/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();
|
||||
/**
|
||||
* Gives access to the navigation results when the navigation is aborted by the user within a data loader.
|
||||
* @internal
|
||||
*/
|
||||
const NAVIGATION_RESULTS_KEY = Symbol();
|
||||
/**
|
||||
* Symbol used to save the initial data on the router.
|
||||
* @internal
|
||||
*/
|
||||
const IS_SSR_KEY = Symbol();
|
||||
|
||||
//#endregion
|
||||
//#region src/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
|
||||
export { ABORT_CONTROLLER_KEY, APP_KEY, IS_SSR_KEY, IS_USE_DATA_LOADER_KEY, LOADER_ENTRIES_KEY, LOADER_SET_KEY, NAVIGATION_RESULTS_KEY, PENDING_LOCATION_KEY, STAGED_NO_VALUE, assign, currentContext, getCurrentContext, isDataLoader, isSubsetOf, setCurrentContext, trackRoute, withLoaderContext };
|
||||
Generated
Vendored
+244
@@ -0,0 +1,244 @@
|
||||
|
||||
//#region src/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();
|
||||
/**
|
||||
* Gives access to the navigation results when the navigation is aborted by the user within a data loader.
|
||||
* @internal
|
||||
*/
|
||||
const NAVIGATION_RESULTS_KEY = Symbol();
|
||||
/**
|
||||
* Symbol used to save the initial data on the router.
|
||||
* @internal
|
||||
*/
|
||||
const IS_SSR_KEY = Symbol();
|
||||
|
||||
//#endregion
|
||||
//#region src/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
|
||||
Object.defineProperty(exports, 'ABORT_CONTROLLER_KEY', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return ABORT_CONTROLLER_KEY;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'APP_KEY', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return APP_KEY;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'IS_SSR_KEY', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return IS_SSR_KEY;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'IS_USE_DATA_LOADER_KEY', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return IS_USE_DATA_LOADER_KEY;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'LOADER_ENTRIES_KEY', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return LOADER_ENTRIES_KEY;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'LOADER_SET_KEY', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return LOADER_SET_KEY;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'NAVIGATION_RESULTS_KEY', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return NAVIGATION_RESULTS_KEY;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'PENDING_LOCATION_KEY', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return PENDING_LOCATION_KEY;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'STAGED_NO_VALUE', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return STAGED_NO_VALUE;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'assign', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return assign;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'currentContext', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return currentContext;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'getCurrentContext', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return getCurrentContext;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'isDataLoader', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return isDataLoader;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'isSubsetOf', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return isSubsetOf;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'setCurrentContext', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return setCurrentContext;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'trackRoute', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return trackRoute;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'withLoaderContext', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return withLoaderContext;
|
||||
}
|
||||
});
|
||||
Generated
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
require('./options-BirY6CFZ.cjs');
|
||||
const require_src = require('./src-DB0pAxuH.cjs');
|
||||
|
||||
//#region src/esbuild.ts
|
||||
var esbuild_default = require_src.src_default.esbuild;
|
||||
|
||||
//#endregion
|
||||
module.exports = esbuild_default;
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import { Options } from "./options-DN4Qs-Nr.cjs";
|
||||
import * as esbuild9 from "esbuild";
|
||||
|
||||
//#region src/esbuild.d.ts
|
||||
declare const _default: (options?: Options | undefined) => esbuild9.Plugin;
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import { Options } from "./options-PFbkwBvS.js";
|
||||
import * as esbuild10 from "esbuild";
|
||||
|
||||
//#region src/esbuild.d.ts
|
||||
declare const _default: (options?: Options | undefined) => esbuild10.Plugin;
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import "./options-vQOEqZ01.js";
|
||||
import { src_default } from "./src-BVnnbDr_.js";
|
||||
|
||||
//#region src/esbuild.ts
|
||||
var esbuild_default = src_default.esbuild;
|
||||
|
||||
//#endregion
|
||||
export { esbuild_default as default };
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
const require_options = require('./options-BirY6CFZ.cjs');
|
||||
const require_src = require('./src-DB0pAxuH.cjs');
|
||||
|
||||
exports.AutoExportLoaders = require_src.AutoExportLoaders;
|
||||
exports.DEFAULT_OPTIONS = require_options.DEFAULT_OPTIONS;
|
||||
exports.EditableTreeNode = require_src.EditableTreeNode;
|
||||
exports.VueRouterAutoImports = require_src.VueRouterAutoImports;
|
||||
exports.createRoutesContext = require_src.createRoutesContext;
|
||||
exports.createTreeNodeValue = require_src.createTreeNodeValue;
|
||||
exports.default = require_src.src_default;
|
||||
exports.getFileBasedRouteName = require_options.getFileBasedRouteName;
|
||||
exports.getPascalCaseRouteName = require_options.getPascalCaseRouteName;
|
||||
Generated
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
import { DEFAULT_OPTIONS, EditableTreeNode, Options, ResolvedOptions, ServerContext, TreeNode, TreeNodeValueParam, TreeNodeValueStatic, createTreeNodeValue, getFileBasedRouteName, getPascalCaseRouteName } from "./options-DN4Qs-Nr.cjs";
|
||||
import "./types-CuECKBwm.cjs";
|
||||
import * as unplugin12 from "unplugin";
|
||||
import * as unplugin10 from "unplugin";
|
||||
import { StringFilter } from "unplugin";
|
||||
import { Plugin } from "vite";
|
||||
|
||||
//#region src/core/context.d.ts
|
||||
declare function createRoutesContext(options: ResolvedOptions): {
|
||||
scanPages: (startWatchers?: boolean) => Promise<void>;
|
||||
writeConfigFiles: () => void;
|
||||
setServerContext: (_server: ServerContext) => void;
|
||||
stopWatcher: () => void;
|
||||
generateRoutes: () => string;
|
||||
generateVueRouterProxy: () => string;
|
||||
definePageTransform(code: string, id: string): unplugin12.Thenable<unplugin12.TransformResult>;
|
||||
};
|
||||
//#endregion
|
||||
//#region src/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/index.d.ts
|
||||
declare const _default: unplugin10.UnpluginInstance<Options | undefined, boolean>;
|
||||
/**
|
||||
* Adds useful auto imports to the AutoImport config:
|
||||
* @example
|
||||
* ```js
|
||||
* import { VueRouterAutoImports } from 'unplugin-vue-router'
|
||||
*
|
||||
* AutoImport({
|
||||
* imports: [VueRouterAutoImports],
|
||||
* }),
|
||||
* ```
|
||||
*/
|
||||
declare const VueRouterAutoImports: Record<string, Array<string | [importName: string, alias: string]>>;
|
||||
//#endregion
|
||||
export { AutoExportLoaders, AutoExportLoadersOptions, DEFAULT_OPTIONS, EditableTreeNode, Options, TreeNode, TreeNodeValueParam, TreeNodeValueStatic, VueRouterAutoImports, createRoutesContext, createTreeNodeValue, _default as default, getFileBasedRouteName, getPascalCaseRouteName };
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
import { DEFAULT_OPTIONS, EditableTreeNode, Options, ResolvedOptions, ServerContext, TreeNode, TreeNodeValueParam, TreeNodeValueStatic, createTreeNodeValue, getFileBasedRouteName, getPascalCaseRouteName } from "./options-PFbkwBvS.js";
|
||||
import "./types-BaFiruHW.js";
|
||||
import * as unplugin12 from "unplugin";
|
||||
import * as unplugin2 from "unplugin";
|
||||
import { StringFilter } from "unplugin";
|
||||
import { Plugin } from "vite";
|
||||
|
||||
//#region src/core/context.d.ts
|
||||
declare function createRoutesContext(options: ResolvedOptions): {
|
||||
scanPages: (startWatchers?: boolean) => Promise<void>;
|
||||
writeConfigFiles: () => void;
|
||||
setServerContext: (_server: ServerContext) => void;
|
||||
stopWatcher: () => void;
|
||||
generateRoutes: () => string;
|
||||
generateVueRouterProxy: () => string;
|
||||
definePageTransform(code: string, id: string): unplugin12.Thenable<unplugin12.TransformResult>;
|
||||
};
|
||||
//#endregion
|
||||
//#region src/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/index.d.ts
|
||||
declare const _default: unplugin2.UnpluginInstance<Options | undefined, boolean>;
|
||||
/**
|
||||
* Adds useful auto imports to the AutoImport config:
|
||||
* @example
|
||||
* ```js
|
||||
* import { VueRouterAutoImports } from 'unplugin-vue-router'
|
||||
*
|
||||
* AutoImport({
|
||||
* imports: [VueRouterAutoImports],
|
||||
* }),
|
||||
* ```
|
||||
*/
|
||||
declare const VueRouterAutoImports: Record<string, Array<string | [importName: string, alias: string]>>;
|
||||
//#endregion
|
||||
export { AutoExportLoaders, AutoExportLoadersOptions, DEFAULT_OPTIONS, EditableTreeNode, Options, TreeNode, TreeNodeValueParam, TreeNodeValueStatic, VueRouterAutoImports, createRoutesContext, createTreeNodeValue, _default as default, getFileBasedRouteName, getPascalCaseRouteName };
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { DEFAULT_OPTIONS, getFileBasedRouteName, getPascalCaseRouteName } from "./options-vQOEqZ01.js";
|
||||
import { AutoExportLoaders, EditableTreeNode, VueRouterAutoImports, createRoutesContext, createTreeNodeValue, src_default } from "./src-BVnnbDr_.js";
|
||||
|
||||
export { AutoExportLoaders, DEFAULT_OPTIONS, EditableTreeNode, VueRouterAutoImports, createRoutesContext, createTreeNodeValue, src_default as default, getFileBasedRouteName, getPascalCaseRouteName };
|
||||
Generated
Vendored
+386
@@ -0,0 +1,386 @@
|
||||
//#region rolldown:runtime
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
||||
key = keys[i];
|
||||
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
||||
get: ((k) => from[k]).bind(null, key),
|
||||
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
||||
});
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
||||
value: mod,
|
||||
enumerable: true
|
||||
}) : target, mod));
|
||||
|
||||
//#endregion
|
||||
const scule = __toESM(require("scule"));
|
||||
const pathe = __toESM(require("pathe"));
|
||||
const local_pkg = __toESM(require("local-pkg"));
|
||||
|
||||
//#region src/core/utils.ts
|
||||
function warn(msg, type = "warn") {
|
||||
console[type](`⚠️ [unplugin-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 = /\/$/;
|
||||
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") {
|
||||
const newAlias = [];
|
||||
merged[key] = newAlias.concat(a.alias || [], b.alias || []);
|
||||
} else if (key === "meta") merged[key] = mergeDeep(a[key] || {}, b[key] || {});
|
||||
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;
|
||||
}
|
||||
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;
|
||||
if (imports.size === 1) {
|
||||
const [[importName, maybeDefault]] = [...imports.entries()];
|
||||
if (maybeDefault === "default") {
|
||||
importStatements += `import ${importName} from '${path}'\n`;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
importStatements += `import { ${Array.from(imports).map(([as, name]) => as === name ? name : `${name} as ${as}`).join(", ")} } from '${path}'\n`;
|
||||
}
|
||||
return importStatements;
|
||||
}
|
||||
get size() {
|
||||
return this.map.size;
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
//#region src/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
|
||||
*/
|
||||
function resolveOverridableOption(defaultValue, value) {
|
||||
return typeof value === "function" ? value(defaultValue) : value ?? defaultValue;
|
||||
}
|
||||
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 experimental = { ...options.experimental };
|
||||
if (experimental.autoExportsDataLoaders) experimental.autoExportsDataLoaders = (Array.isArray(experimental.autoExportsDataLoaders) ? experimental.autoExportsDataLoaders : [experimental.autoExportsDataLoaders]).map((path) => (0, pathe.resolve)(root, path));
|
||||
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, 'ImportsMap', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return ImportsMap;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, '__toESM', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return __toESM;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'appendExtensionListToPattern', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return appendExtensionListToPattern;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, 'asRoutePath', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return asRoutePath;
|
||||
}
|
||||
});
|
||||
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, '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, 'warn', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return warn;
|
||||
}
|
||||
});
|
||||
Generated
Vendored
+741
@@ -0,0 +1,741 @@
|
||||
import { RouteMeta, RouteRecordRaw } from "vue-router";
|
||||
|
||||
//#region src/core/customBlock.d.ts
|
||||
interface CustomRouteBlock extends Partial<Omit<RouteRecordRaw, 'components' | 'component' | 'children' | 'beforeEnter' | 'name'>> {
|
||||
name?: string | undefined | false;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/core/treeNodeValue.d.ts
|
||||
declare const enum TreeNodeType {
|
||||
static = 0,
|
||||
group = 1,
|
||||
param = 2,
|
||||
}
|
||||
interface RouteRecordOverride extends Partial<Pick<RouteRecordRaw, 'meta' | 'props' | 'alias' | 'path'>> {
|
||||
name?: string | undefined | false;
|
||||
}
|
||||
type SubSegment = string | TreeRouteParam;
|
||||
declare class _TreeNodeValueBase {
|
||||
/**
|
||||
* flag based on the type of the segment
|
||||
*/
|
||||
_type: TreeNodeType;
|
||||
parent: TreeNodeValue | undefined;
|
||||
/**
|
||||
* segment as defined by the file structure e.g. keeps the `index` name, `(group-name)`
|
||||
*/
|
||||
rawSegment: string;
|
||||
/**
|
||||
* transformed version of the segment into a vue-router path. e.g. `'index'` becomes `''` and `[param]` becomes
|
||||
* `:param`, `prefix-[param]-end` becomes `prefix-:param-end`.
|
||||
*/
|
||||
pathSegment: string;
|
||||
/**
|
||||
* Array of sub segments. This is usually one single elements but can have more for paths like `prefix-[param]-end.vue`
|
||||
*/
|
||||
subSegments: SubSegment[];
|
||||
/**
|
||||
* Overrides defined by each file. The map is necessary to handle named views.
|
||||
*/
|
||||
private _overrides;
|
||||
/**
|
||||
* View name (Vue Router feature) mapped to their corresponding file. By default, the view name is `default` unless
|
||||
* specified with a `@` e.g. `[email protected]` will have a view name of `aux`.
|
||||
*/
|
||||
components: Map<string, string>;
|
||||
constructor(rawSegment: string, parent: TreeNodeValue | undefined, pathSegment?: string, subSegments?: SubSegment[]);
|
||||
/**
|
||||
* Path of the node. Can be absolute or not. If it has been overridden, it
|
||||
* will return the overridden path.
|
||||
*/
|
||||
get path(): string;
|
||||
/**
|
||||
* Full path of the node including parent nodes.
|
||||
*/
|
||||
get fullPath(): string;
|
||||
toString(): string;
|
||||
isParam(): this is TreeNodeValueParam;
|
||||
isStatic(): this is TreeNodeValueStatic;
|
||||
isGroup(): this is TreeNodeValueGroup;
|
||||
get overrides(): RouteRecordOverride;
|
||||
setOverride(filePath: string, routeBlock: CustomRouteBlock | undefined): void;
|
||||
/**
|
||||
* Remove all overrides for a given key.
|
||||
*
|
||||
* @param key - key to remove from the override, e.g. path, name, etc
|
||||
*/
|
||||
removeOverride(key: keyof CustomRouteBlock): void;
|
||||
/**
|
||||
* Add an override to the current node by merging with the existing values.
|
||||
*
|
||||
* @param filePath - The file path to add to the override
|
||||
* @param routeBlock - The route block to add to the override
|
||||
*/
|
||||
mergeOverride(filePath: string, routeBlock: CustomRouteBlock): void;
|
||||
/**
|
||||
* Add an override to the current node using the special file path `@@edits` that makes this added at build time.
|
||||
*
|
||||
* @param routeBlock - The route block to add to the override
|
||||
*/
|
||||
addEditOverride(routeBlock: CustomRouteBlock): void;
|
||||
/**
|
||||
* Set a specific value in the _edits_ override.
|
||||
*
|
||||
* @param key - key to set in the override, e.g. path, name, etc
|
||||
* @param value - value to set in the override
|
||||
*/
|
||||
setEditOverride<K extends keyof RouteRecordOverride>(key: K, value: RouteRecordOverride[K]): void;
|
||||
}
|
||||
declare class TreeNodeValueStatic extends _TreeNodeValueBase {
|
||||
_type: TreeNodeType.static;
|
||||
constructor(rawSegment: string, parent: TreeNodeValue | undefined, pathSegment?: string);
|
||||
}
|
||||
declare class TreeNodeValueGroup extends _TreeNodeValueBase {
|
||||
_type: TreeNodeType.group;
|
||||
groupName: string;
|
||||
constructor(rawSegment: string, parent: TreeNodeValue | undefined, pathSegment: string, groupName: string);
|
||||
}
|
||||
interface TreeRouteParam {
|
||||
paramName: string;
|
||||
modifier: string;
|
||||
optional: boolean;
|
||||
repeatable: boolean;
|
||||
isSplat: boolean;
|
||||
}
|
||||
declare class TreeNodeValueParam extends _TreeNodeValueBase {
|
||||
params: TreeRouteParam[];
|
||||
_type: TreeNodeType.param;
|
||||
constructor(rawSegment: string, parent: TreeNodeValue | undefined, params: TreeRouteParam[], pathSegment: string, subSegments: SubSegment[]);
|
||||
}
|
||||
type TreeNodeValue = TreeNodeValueStatic | TreeNodeValueParam | TreeNodeValueGroup;
|
||||
interface TreeNodeValueOptions extends ParseSegmentOptions {
|
||||
/**
|
||||
* Format of the route path. Defaults to `file` which is the format used by unplugin-vue-router and matches the file
|
||||
* structure (e.g. `index`, ``, or `users/[id]`). In `path` format, routes are expected in the format of vue-router
|
||||
* (e.g. `/` or '/users/:id' ).
|
||||
*
|
||||
* @default `'file'`
|
||||
*/
|
||||
format?: 'file' | 'path';
|
||||
}
|
||||
/**
|
||||
* Creates a new TreeNodeValue based on the segment. The result can be a static segment, group segment or a param segment.
|
||||
*
|
||||
* @param segment - path segment
|
||||
* @param parent - parent node
|
||||
* @param options - options
|
||||
*/
|
||||
declare function createTreeNodeValue(segment: string, parent?: TreeNodeValue, opts?: TreeNodeValueOptions): TreeNodeValue;
|
||||
/**
|
||||
* Options passed to `parseSegment()`to control how a segment of a file path is parsed. e.g. in `/users/[id]`, `users`
|
||||
* and `[id]` are segments.
|
||||
*/
|
||||
interface ParseSegmentOptions {
|
||||
/**
|
||||
* Should we allow dot nesting in the param name. e.g. `users.[id]` will be parsed as `users/[id]` if this is `true`,
|
||||
* nesting. Note this only works for the `file` format.
|
||||
*
|
||||
* @default `true`
|
||||
*/
|
||||
dotNesting?: boolean;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/core/tree.d.ts
|
||||
interface TreeNodeOptions extends ResolvedOptions {
|
||||
treeNodeOptions?: TreeNodeValueOptions;
|
||||
}
|
||||
declare class TreeNode {
|
||||
/**
|
||||
* value of the node
|
||||
*/
|
||||
value: TreeNodeValue;
|
||||
/**
|
||||
* children of the node
|
||||
*/
|
||||
children: Map<string, TreeNode>;
|
||||
/**
|
||||
* Parent node.
|
||||
*/
|
||||
parent: TreeNode | undefined;
|
||||
/**
|
||||
* Plugin options taken into account by the tree.
|
||||
*/
|
||||
options: TreeNodeOptions;
|
||||
/**
|
||||
* Should this page import the page info
|
||||
*/
|
||||
hasDefinePage: boolean;
|
||||
/**
|
||||
* Creates a new tree node.
|
||||
*
|
||||
* @param options - TreeNodeOptions shared by all nodes
|
||||
* @param pathSegment - path segment of this node e.g. `users` or `:id`
|
||||
* @param parent
|
||||
*/
|
||||
constructor(options: TreeNodeOptions, pathSegment: string, parent?: TreeNode);
|
||||
/**
|
||||
* Adds a path to the tree. `path` cannot start with a `/`.
|
||||
*
|
||||
* @param path - path segment to insert. **It shouldn't contain the file extension**
|
||||
* @param filePath - file path, must be a file (not a folder)
|
||||
*/
|
||||
insert(path: string, filePath: string): TreeNode;
|
||||
/**
|
||||
* Adds a path that has already been parsed to the tree. `path` cannot start with a `/`. This method is similar to
|
||||
* `insert` but the path argument should be already parsed. e.g. `users/:id` for a file named `users/[id].vue`.
|
||||
*
|
||||
* @param path - path segment to insert, already parsed (e.g. users/:id)
|
||||
* @param filePath - file path, defaults to path for convenience and testing
|
||||
*/
|
||||
insertParsedPath(path: string, filePath?: string): TreeNode;
|
||||
/**
|
||||
* Saves a custom route block for a specific file path. The file path is used as a key. Some special file paths will
|
||||
* have a lower or higher priority.
|
||||
*
|
||||
* @param filePath - file path where the custom block is located
|
||||
* @param routeBlock - custom block to set
|
||||
*/
|
||||
setCustomRouteBlock(filePath: string, routeBlock: CustomRouteBlock | undefined): void;
|
||||
/**
|
||||
* Generator that yields all descendants without sorting.
|
||||
* Use with Array.from() for now, native .map() support in Node 22+.
|
||||
*/
|
||||
getChildrenDeep(): Generator<TreeNode>;
|
||||
/**
|
||||
* Comparator function for sorting TreeNodes.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static compare(a: TreeNode, b: TreeNode): number;
|
||||
/**
|
||||
* Get the children of this node sorted by their path.
|
||||
*/
|
||||
getChildrenSorted(): TreeNode[];
|
||||
/**
|
||||
* Calls {@link getChildrenDeep} and sorts the result by path in the end.
|
||||
*/
|
||||
getChildrenDeepSorted(): TreeNode[];
|
||||
/**
|
||||
* Delete and detach itself from the tree.
|
||||
*/
|
||||
delete(): void;
|
||||
/**
|
||||
* Remove a route from the tree. The path shouldn't start with a `/` but it can be a nested one. e.g. `foo/bar`.
|
||||
* The `path` should be relative to the page folder.
|
||||
*
|
||||
* @param path - path segment of the file
|
||||
*/
|
||||
remove(path: string): void;
|
||||
/**
|
||||
* Returns the route path of the node without parent paths. If the path was overridden, it returns the override.
|
||||
*/
|
||||
get path(): string;
|
||||
/**
|
||||
* Returns the route path of the node including parent paths.
|
||||
*/
|
||||
get fullPath(): string;
|
||||
get components(): {
|
||||
[k: string]: string;
|
||||
};
|
||||
/**
|
||||
* Returns the route name of the node. If the name was overridden, it returns the override.
|
||||
*/
|
||||
get name(): string | false;
|
||||
/**
|
||||
* Returns the meta property as an object.
|
||||
*/
|
||||
get metaAsObject(): Readonly<RouteMeta>;
|
||||
/**
|
||||
* Returns the JSON string of the meta object of the node. If the meta was overridden, it returns the override. If
|
||||
* there is no override, it returns an empty string.
|
||||
*/
|
||||
get meta(): string;
|
||||
get params(): TreeRouteParam[];
|
||||
/**
|
||||
* Returns wether this tree node is the root node of the tree.
|
||||
*
|
||||
* @returns true if the node is the root node
|
||||
*/
|
||||
isRoot(): this is PrefixTree;
|
||||
toString(): string;
|
||||
}
|
||||
/**
|
||||
* Creates a new prefix tree. This is meant to only be the root node. It has access to extra methods that only make
|
||||
* sense on the root node.
|
||||
*/
|
||||
declare class PrefixTree extends TreeNode {
|
||||
map: Map<string, TreeNode>;
|
||||
constructor(options: ResolvedOptions);
|
||||
insert(path: string, filePath: string): TreeNode;
|
||||
/**
|
||||
* Returns the tree node of the given file path.
|
||||
*
|
||||
* @param filePath - file path of the tree node to get
|
||||
*/
|
||||
getChild(filePath: string): TreeNode | undefined;
|
||||
/**
|
||||
* Removes the tree node of the given file path.
|
||||
*
|
||||
* @param filePath - file path of the tree node to remove
|
||||
*/
|
||||
removeChild(filePath: string): void;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/core/utils.d.ts
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
declare function getPascalCaseRouteName(node: TreeNode): string;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
declare function getFileBasedRouteName(node: TreeNode): string;
|
||||
//#endregion
|
||||
//#region src/core/extendRoutes.d.ts
|
||||
/**
|
||||
* A route node that can be modified by the user. The tree can be iterated to be traversed.
|
||||
* @example
|
||||
* ```js
|
||||
* [...node] // creates an array of all the children
|
||||
* for (const child of node) {
|
||||
* // do something with the child node
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
declare class EditableTreeNode {
|
||||
private node;
|
||||
constructor(node: TreeNode);
|
||||
/**
|
||||
* Remove and detach the current route node from the tree. Subsequently, its children will be removed as well.
|
||||
*/
|
||||
delete(): void;
|
||||
/**
|
||||
* Inserts a new route as a child of this route. This route cannot use `definePage()`. If it was meant to be included,
|
||||
* add it to the `routesFolder` option.
|
||||
*
|
||||
* @param path - path segment to insert. Note this is relative to the current route. **It shouldn't start with `/`**. If it does, it will be added to the root of the tree.
|
||||
* @param filePath - file path
|
||||
* @returns the new editable route node
|
||||
*/
|
||||
insert(path: string, filePath: string): EditableTreeNode;
|
||||
/**
|
||||
* Get an editable version of the parent node if it exists.
|
||||
*/
|
||||
get parent(): EditableTreeNode | undefined;
|
||||
/**
|
||||
* Return a Map of the files associated to the current route. The key of the map represents the name of the view (Vue
|
||||
* Router feature) while the value is the **resolved** file path.
|
||||
* By default, the name of the view is `default`.
|
||||
*/
|
||||
get components(): Map<string, string>;
|
||||
/**
|
||||
* Alias for `route.components.get('default')`.
|
||||
*/
|
||||
get component(): string | undefined;
|
||||
/**
|
||||
* Name of the route. Note that **all routes are named** but when the final `routes` array is generated, routes
|
||||
* without a `component` will not include their `name` property to avoid accidentally navigating to them and display
|
||||
* nothing.
|
||||
* @see {@link isPassThrough}
|
||||
*/
|
||||
get name(): string | false;
|
||||
/**
|
||||
* Override the name of the route.
|
||||
*/
|
||||
set name(name: string | undefined);
|
||||
/**
|
||||
* Whether the route is a pass-through route. A pass-through route is a route that does not have a component and is
|
||||
* used to group other routes under the same prefix `path` and/or `meta` properties.
|
||||
*/
|
||||
get isPassThrough(): boolean;
|
||||
/**
|
||||
* Meta property of the route as an object. Note this property is readonly and will be serialized as JSON. It won't contain the meta properties defined with `definePage()` as it could contain expressions **but it does contain the meta properties defined with `<route>` blocks**.
|
||||
*/
|
||||
get meta(): Readonly<RouteMeta>;
|
||||
/**
|
||||
* Override the meta property of the route. This will discard any other meta property defined with `<route>` blocks or
|
||||
* through other means. If you want to keep the existing meta properties, use `addToMeta`.
|
||||
* @see {@link addToMeta}
|
||||
*/
|
||||
set meta(meta: RouteMeta);
|
||||
/**
|
||||
* Add meta properties to the route keeping the existing ones. The passed object will be deeply merged with the
|
||||
* existing meta object if any. Note that the meta property is later on serialized as JSON so you can't pass functions
|
||||
* or any other non-serializable value.
|
||||
*/
|
||||
addToMeta(meta: Partial<RouteMeta>): void;
|
||||
/**
|
||||
* Path of the route without parent paths.
|
||||
*/
|
||||
get path(): string;
|
||||
/**
|
||||
* Override the path of the route. You must ensure `params` match with the existing path.
|
||||
*/
|
||||
set path(path: string);
|
||||
/**
|
||||
* Alias of the route.
|
||||
*/
|
||||
get alias(): string | string[] | undefined;
|
||||
/**
|
||||
* Add an alias to the route.
|
||||
*
|
||||
* @param alias - Alias to add to the route
|
||||
*/
|
||||
addAlias(alias: CustomRouteBlock['alias']): void;
|
||||
/**
|
||||
* Array of the route params and all of its parent's params. Note that changing the params will not update the path,
|
||||
* you need to update both.
|
||||
*/
|
||||
get params(): TreeRouteParam[];
|
||||
/**
|
||||
* Path of the route including parent paths.
|
||||
*/
|
||||
get fullPath(): string;
|
||||
/**
|
||||
* Computes an array of EditableTreeNode from the current node. Differently from iterating over the tree, this method
|
||||
* **only returns direct children**.
|
||||
*/
|
||||
get children(): EditableTreeNode[];
|
||||
/**
|
||||
* DFS traversal of the tree.
|
||||
* @example
|
||||
* ```ts
|
||||
* for (const node of tree) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
traverseDFS(): Generator<EditableTreeNode, void, unknown>;
|
||||
[Symbol.iterator](): Generator<EditableTreeNode, void, unknown>;
|
||||
/**
|
||||
* BFS traversal of the tree as a generator.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* for (const node of tree) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
traverseBFS(): Generator<EditableTreeNode, void, unknown>;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/utils/index.d.ts
|
||||
/**
|
||||
* Maybe a promise maybe not
|
||||
* @internal
|
||||
*/
|
||||
type _Awaitable<T> = T | PromiseLike<T>;
|
||||
/**
|
||||
* Creates a union type that still allows autocompletion for strings.
|
||||
*@internal
|
||||
*/
|
||||
//#endregion
|
||||
//#region src/options.d.ts
|
||||
/**
|
||||
* Options for a routes folder.
|
||||
*/
|
||||
interface RoutesFolderOption {
|
||||
/**
|
||||
* Folder to scan files that should be used for routes. **Cannot be a glob**, use the `path`, `filePatterns`, and
|
||||
* `exclude` options to filter out files. This section will **be removed** from the resulting path.
|
||||
*/
|
||||
src: string;
|
||||
/**
|
||||
* Prefix to add to the route path **as is**. Defaults to `''`. Can also be a function
|
||||
* to reuse parts of the filepath, in that case you should return a **modified version of the filepath**.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* {
|
||||
* src: 'src/pages',
|
||||
* // this is equivalent to the default behavior
|
||||
* path: (file) => file.slice(file.lastIndexOf('src/pages') + 'src/pages'.length
|
||||
* },
|
||||
* {
|
||||
* src: 'src/features',
|
||||
* // match all files (note the \ is not needed in real code)
|
||||
* filePatterns: '*/pages/**\/',
|
||||
* path: (file) => {
|
||||
* const prefix = 'src/features'
|
||||
* // remove the everything before src/features and removes /pages
|
||||
* // /src/features/feature1/pages/index.vue -> feature1/index.vue
|
||||
* return file.slice(file.lastIndexOf(prefix) + prefix.length + 1).replace('/pages', '')
|
||||
* },
|
||||
* },
|
||||
* {
|
||||
* src: 'src/docs',
|
||||
* // adds a prefix with a param
|
||||
* path: 'docs/[lang]/',
|
||||
* },
|
||||
* ```
|
||||
*/
|
||||
path?: string | ((filepath: string) => string);
|
||||
/**
|
||||
* Allows to override the global `filePattern` option for this folder. It can also extend the global values by passing
|
||||
* a function that returns an array.
|
||||
*/
|
||||
filePatterns?: _OverridableOption<string[], string | string[]>;
|
||||
/**
|
||||
* Allows to override the global `exclude` option for this folder. It can
|
||||
* also extend the global values by passing a function that returns an array.
|
||||
*/
|
||||
exclude?: _OverridableOption<string[], string | string[]>;
|
||||
/**
|
||||
* Allows to override the global `extensions` option for this folder. It can
|
||||
* also extend the global values by passing a function that returns an array.
|
||||
* The provided extensions are removed from the final route. For example,
|
||||
* `.page.vue` allows to suffix all pages with `.page.vue` and remove it from
|
||||
* the route name.
|
||||
*/
|
||||
extensions?: _OverridableOption<string[]>;
|
||||
}
|
||||
/**
|
||||
* Normalized options for a routes folder.
|
||||
*/
|
||||
interface RoutesFolderOptionResolved extends RoutesFolderOption {
|
||||
path: string | ((filepath: string) => string);
|
||||
/**
|
||||
* Final glob pattern to match files in the folder.
|
||||
*/
|
||||
pattern: string[];
|
||||
filePatterns: string[];
|
||||
exclude: string[];
|
||||
extensions: string[];
|
||||
}
|
||||
type _OverridableOption<T, AllowedTypes = T> = AllowedTypes | ((existing: T) => T);
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
declare function resolveOverridableOption<T>(defaultValue: T, value?: _OverridableOption<T, T>): T;
|
||||
type _RoutesFolder = string | RoutesFolderOption;
|
||||
type RoutesFolder = _RoutesFolder[] | _RoutesFolder;
|
||||
/**
|
||||
* unplugin-vue-router plugin options.
|
||||
*/
|
||||
interface Options {
|
||||
/**
|
||||
* Extensions of files to be considered as pages. Cannot be empty. This allows to strip a
|
||||
* bigger part of the filename e.g. `index.page.vue` -> `index` if an extension of `.page.vue` is provided.
|
||||
* @default `['.vue']`
|
||||
*/
|
||||
extensions?: string[];
|
||||
/**
|
||||
* Folder(s) to scan for files and generate routes. Can also be an array if you want to add multiple
|
||||
* folders, or an object if you want to define a route prefix. Supports glob patterns but must be a folder, use
|
||||
* `extensions` and `exclude` to filter files.
|
||||
*
|
||||
* @default `"src/pages"`
|
||||
*/
|
||||
routesFolder?: RoutesFolder;
|
||||
/**
|
||||
* Array of `picomatch` globs to ignore. Note the globs are relative to the cwd, so avoid writing
|
||||
* something like `['ignored']` to match folders named that way, instead provide a path similar to the `routesFolder`:
|
||||
* `['src/pages/ignored/**']` or use `['**/ignored']` to match every folder named `ignored`.
|
||||
* @default `[]`
|
||||
*/
|
||||
exclude?: string[] | string;
|
||||
/**
|
||||
* Pattern to match files in the `routesFolder`. Defaults to `**/*` plus a combination of all the possible extensions,
|
||||
* e.g. `**/*.{vue,md}` if `extensions` is set to `['.vue', '.md']`. This is relative to the {@link RoutesFolderOption['src']} and
|
||||
* @default `['**/*']`
|
||||
*/
|
||||
filePatterns?: string[] | string;
|
||||
/**
|
||||
* Method to generate the name of a route. It's recommended to keep the default value to guarantee a consistent,
|
||||
* unique, and predictable naming.
|
||||
*/
|
||||
getRouteName?: (node: TreeNode) => string;
|
||||
/**
|
||||
* Allows to extend a route by modifying its node, adding children, or even deleting it. This will be invoked once for
|
||||
* each route.
|
||||
*
|
||||
* @param route - {@link EditableTreeNode} of the route to extend
|
||||
*/
|
||||
extendRoute?: (route: EditableTreeNode) => _Awaitable<void>;
|
||||
/**
|
||||
* Allows to do some changes before writing the files. This will be invoked **every time** the files need to be written.
|
||||
*
|
||||
* @param rootRoute - {@link EditableTreeNode} of the root route
|
||||
*/
|
||||
beforeWriteFiles?: (rootRoute: EditableTreeNode) => _Awaitable<void>;
|
||||
/**
|
||||
* Defines how page components should be imported. Defaults to dynamic imports to enable lazy loading of pages.
|
||||
* @default `'async'`
|
||||
*/
|
||||
importMode?: 'sync' | 'async' | ((filepath: string) => 'sync' | 'async');
|
||||
/**
|
||||
* Root of the project. All paths are resolved relatively to this one.
|
||||
* @default `process.cwd()`
|
||||
*/
|
||||
root?: string;
|
||||
/**
|
||||
* Language for `<route>` blocks in SFC files.
|
||||
* @default `'json5'`
|
||||
*/
|
||||
routeBlockLang?: 'yaml' | 'yml' | 'json5' | 'json';
|
||||
/**
|
||||
* Should we generate d.ts files or ont. Defaults to `true` if `typescript` is installed. Can be set to a string of
|
||||
* the filepath to write the d.ts files to. By default it will generate a file named `typed-router.d.ts`.
|
||||
* @default `true`
|
||||
*/
|
||||
dts?: boolean | string;
|
||||
/**
|
||||
* Allows inspection by vite-plugin-inspect by not adding the leading `\0` to the id of virtual modules.
|
||||
* @internal
|
||||
*/
|
||||
_inspect?: boolean;
|
||||
/**
|
||||
* Activates debug logs.
|
||||
*/
|
||||
logs?: boolean;
|
||||
/**
|
||||
* @inheritDoc ParseSegmentOptions
|
||||
*/
|
||||
pathParser?: ParseSegmentOptions;
|
||||
/**
|
||||
* Whether to watch the files for changes.
|
||||
*
|
||||
* Defaults to `true` unless the `CI` environment variable is set.
|
||||
*
|
||||
* @default `!process.env.CI`
|
||||
*/
|
||||
watch?: boolean;
|
||||
/**
|
||||
* Experimental options. **Warning**: these can change or be removed at any time, even it patch releases. Keep an eye
|
||||
* on the Changelog.
|
||||
*/
|
||||
experimental?: {
|
||||
/**
|
||||
* (Vite only). File paths or globs where loaders are exported. This will be used to filter out imported loaders and
|
||||
* automatically re export them in page components. You can for example set this to `'src/loaders/**\/*'` (without
|
||||
* the backslash) to automatically re export any imported variable from files in the `src/loaders` folder within a
|
||||
* page component.
|
||||
*/
|
||||
autoExportsDataLoaders?: string | string[];
|
||||
};
|
||||
}
|
||||
declare const DEFAULT_OPTIONS: {
|
||||
extensions: string[];
|
||||
exclude: never[];
|
||||
routesFolder: string;
|
||||
filePatterns: string[];
|
||||
routeBlockLang: "json5";
|
||||
getRouteName: typeof getFileBasedRouteName;
|
||||
importMode: "async";
|
||||
root: string;
|
||||
dts: boolean;
|
||||
logs: false;
|
||||
_inspect: false;
|
||||
pathParser: {
|
||||
dotNesting: true;
|
||||
};
|
||||
watch: boolean;
|
||||
experimental: {};
|
||||
};
|
||||
interface ServerContext {
|
||||
invalidate: (module: string) => void;
|
||||
updateRoutes: () => Promise<void>;
|
||||
reload: () => void;
|
||||
}
|
||||
/**
|
||||
* Normalize user options with defaults and resolved paths.
|
||||
*
|
||||
* @param options - user provided options
|
||||
* @returns normalized options
|
||||
*/
|
||||
declare function resolveOptions(options: Options): {
|
||||
experimental: {
|
||||
autoExportsDataLoaders?: string | string[];
|
||||
};
|
||||
routesFolder: {
|
||||
src: string;
|
||||
filePatterns: string[] | ((existing: string[]) => string[]) | undefined;
|
||||
exclude: string[] | ((existing: string[]) => string[]) | undefined;
|
||||
/**
|
||||
* Prefix to add to the route path **as is**. Defaults to `''`. Can also be a function
|
||||
* to reuse parts of the filepath, in that case you should return a **modified version of the filepath**.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* {
|
||||
* src: 'src/pages',
|
||||
* // this is equivalent to the default behavior
|
||||
* path: (file) => file.slice(file.lastIndexOf('src/pages') + 'src/pages'.length
|
||||
* },
|
||||
* {
|
||||
* src: 'src/features',
|
||||
* // match all files (note the \ is not needed in real code)
|
||||
* filePatterns: '*/pages/**\/',
|
||||
* path: (file) => {
|
||||
* const prefix = 'src/features'
|
||||
* // remove the everything before src/features and removes /pages
|
||||
* // /src/features/feature1/pages/index.vue -> feature1/index.vue
|
||||
* return file.slice(file.lastIndexOf(prefix) + prefix.length + 1).replace('/pages', '')
|
||||
* },
|
||||
* },
|
||||
* {
|
||||
* src: 'src/docs',
|
||||
* // adds a prefix with a param
|
||||
* path: 'docs/[lang]/',
|
||||
* },
|
||||
* ```
|
||||
*/
|
||||
path?: string | ((filepath: string) => string);
|
||||
/**
|
||||
* Allows to override the global `extensions` option for this folder. It can
|
||||
* also extend the global values by passing a function that returns an array.
|
||||
* The provided extensions are removed from the final route. For example,
|
||||
* `.page.vue` allows to suffix all pages with `.page.vue` and remove it from
|
||||
* the route name.
|
||||
*/
|
||||
extensions?: _OverridableOption<string[]>;
|
||||
}[];
|
||||
filePatterns: string[];
|
||||
exclude: string[];
|
||||
extensions: string[];
|
||||
getRouteName: typeof getFileBasedRouteName;
|
||||
/**
|
||||
* Allows to extend a route by modifying its node, adding children, or even deleting it. This will be invoked once for
|
||||
* each route.
|
||||
*
|
||||
* @param route - {@link EditableTreeNode} of the route to extend
|
||||
*/
|
||||
extendRoute?: (route: EditableTreeNode) => _Awaitable<void>;
|
||||
/**
|
||||
* Allows to do some changes before writing the files. This will be invoked **every time** the files need to be written.
|
||||
*
|
||||
* @param rootRoute - {@link EditableTreeNode} of the root route
|
||||
*/
|
||||
beforeWriteFiles?: (rootRoute: EditableTreeNode) => _Awaitable<void>;
|
||||
importMode: "sync" | "async" | ((filepath: string) => "sync" | "async");
|
||||
root: string;
|
||||
routeBlockLang: "yaml" | "yml" | "json5" | "json";
|
||||
dts: boolean | string;
|
||||
_inspect: boolean;
|
||||
logs: boolean;
|
||||
pathParser: ParseSegmentOptions;
|
||||
watch: boolean;
|
||||
};
|
||||
type ResolvedOptions = ReturnType<typeof resolveOptions>;
|
||||
/**
|
||||
* Merge all the possible extensions as an array of unique values
|
||||
* @param options - user provided options
|
||||
* @internal
|
||||
*/
|
||||
declare function mergeAllExtensions(options: ResolvedOptions): string[];
|
||||
//#endregion
|
||||
export { DEFAULT_OPTIONS, EditableTreeNode, Options, ResolvedOptions, RoutesFolder, RoutesFolderOption, RoutesFolderOptionResolved, ServerContext, TreeNode, TreeNodeValueParam, TreeNodeValueStatic, _OverridableOption, _RoutesFolder, createTreeNodeValue, getFileBasedRouteName, getPascalCaseRouteName, mergeAllExtensions, resolveOptions, resolveOverridableOption };
|
||||
Generated
Vendored
+741
@@ -0,0 +1,741 @@
|
||||
import { RouteMeta, RouteRecordRaw } from "vue-router";
|
||||
|
||||
//#region src/core/customBlock.d.ts
|
||||
interface CustomRouteBlock extends Partial<Omit<RouteRecordRaw, 'components' | 'component' | 'children' | 'beforeEnter' | 'name'>> {
|
||||
name?: string | undefined | false;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/core/treeNodeValue.d.ts
|
||||
declare const enum TreeNodeType {
|
||||
static = 0,
|
||||
group = 1,
|
||||
param = 2,
|
||||
}
|
||||
interface RouteRecordOverride extends Partial<Pick<RouteRecordRaw, 'meta' | 'props' | 'alias' | 'path'>> {
|
||||
name?: string | undefined | false;
|
||||
}
|
||||
type SubSegment = string | TreeRouteParam;
|
||||
declare class _TreeNodeValueBase {
|
||||
/**
|
||||
* flag based on the type of the segment
|
||||
*/
|
||||
_type: TreeNodeType;
|
||||
parent: TreeNodeValue | undefined;
|
||||
/**
|
||||
* segment as defined by the file structure e.g. keeps the `index` name, `(group-name)`
|
||||
*/
|
||||
rawSegment: string;
|
||||
/**
|
||||
* transformed version of the segment into a vue-router path. e.g. `'index'` becomes `''` and `[param]` becomes
|
||||
* `:param`, `prefix-[param]-end` becomes `prefix-:param-end`.
|
||||
*/
|
||||
pathSegment: string;
|
||||
/**
|
||||
* Array of sub segments. This is usually one single elements but can have more for paths like `prefix-[param]-end.vue`
|
||||
*/
|
||||
subSegments: SubSegment[];
|
||||
/**
|
||||
* Overrides defined by each file. The map is necessary to handle named views.
|
||||
*/
|
||||
private _overrides;
|
||||
/**
|
||||
* View name (Vue Router feature) mapped to their corresponding file. By default, the view name is `default` unless
|
||||
* specified with a `@` e.g. `[email protected]` will have a view name of `aux`.
|
||||
*/
|
||||
components: Map<string, string>;
|
||||
constructor(rawSegment: string, parent: TreeNodeValue | undefined, pathSegment?: string, subSegments?: SubSegment[]);
|
||||
/**
|
||||
* Path of the node. Can be absolute or not. If it has been overridden, it
|
||||
* will return the overridden path.
|
||||
*/
|
||||
get path(): string;
|
||||
/**
|
||||
* Full path of the node including parent nodes.
|
||||
*/
|
||||
get fullPath(): string;
|
||||
toString(): string;
|
||||
isParam(): this is TreeNodeValueParam;
|
||||
isStatic(): this is TreeNodeValueStatic;
|
||||
isGroup(): this is TreeNodeValueGroup;
|
||||
get overrides(): RouteRecordOverride;
|
||||
setOverride(filePath: string, routeBlock: CustomRouteBlock | undefined): void;
|
||||
/**
|
||||
* Remove all overrides for a given key.
|
||||
*
|
||||
* @param key - key to remove from the override, e.g. path, name, etc
|
||||
*/
|
||||
removeOverride(key: keyof CustomRouteBlock): void;
|
||||
/**
|
||||
* Add an override to the current node by merging with the existing values.
|
||||
*
|
||||
* @param filePath - The file path to add to the override
|
||||
* @param routeBlock - The route block to add to the override
|
||||
*/
|
||||
mergeOverride(filePath: string, routeBlock: CustomRouteBlock): void;
|
||||
/**
|
||||
* Add an override to the current node using the special file path `@@edits` that makes this added at build time.
|
||||
*
|
||||
* @param routeBlock - The route block to add to the override
|
||||
*/
|
||||
addEditOverride(routeBlock: CustomRouteBlock): void;
|
||||
/**
|
||||
* Set a specific value in the _edits_ override.
|
||||
*
|
||||
* @param key - key to set in the override, e.g. path, name, etc
|
||||
* @param value - value to set in the override
|
||||
*/
|
||||
setEditOverride<K extends keyof RouteRecordOverride>(key: K, value: RouteRecordOverride[K]): void;
|
||||
}
|
||||
declare class TreeNodeValueStatic extends _TreeNodeValueBase {
|
||||
_type: TreeNodeType.static;
|
||||
constructor(rawSegment: string, parent: TreeNodeValue | undefined, pathSegment?: string);
|
||||
}
|
||||
declare class TreeNodeValueGroup extends _TreeNodeValueBase {
|
||||
_type: TreeNodeType.group;
|
||||
groupName: string;
|
||||
constructor(rawSegment: string, parent: TreeNodeValue | undefined, pathSegment: string, groupName: string);
|
||||
}
|
||||
interface TreeRouteParam {
|
||||
paramName: string;
|
||||
modifier: string;
|
||||
optional: boolean;
|
||||
repeatable: boolean;
|
||||
isSplat: boolean;
|
||||
}
|
||||
declare class TreeNodeValueParam extends _TreeNodeValueBase {
|
||||
params: TreeRouteParam[];
|
||||
_type: TreeNodeType.param;
|
||||
constructor(rawSegment: string, parent: TreeNodeValue | undefined, params: TreeRouteParam[], pathSegment: string, subSegments: SubSegment[]);
|
||||
}
|
||||
type TreeNodeValue = TreeNodeValueStatic | TreeNodeValueParam | TreeNodeValueGroup;
|
||||
interface TreeNodeValueOptions extends ParseSegmentOptions {
|
||||
/**
|
||||
* Format of the route path. Defaults to `file` which is the format used by unplugin-vue-router and matches the file
|
||||
* structure (e.g. `index`, ``, or `users/[id]`). In `path` format, routes are expected in the format of vue-router
|
||||
* (e.g. `/` or '/users/:id' ).
|
||||
*
|
||||
* @default `'file'`
|
||||
*/
|
||||
format?: 'file' | 'path';
|
||||
}
|
||||
/**
|
||||
* Creates a new TreeNodeValue based on the segment. The result can be a static segment, group segment or a param segment.
|
||||
*
|
||||
* @param segment - path segment
|
||||
* @param parent - parent node
|
||||
* @param options - options
|
||||
*/
|
||||
declare function createTreeNodeValue(segment: string, parent?: TreeNodeValue, opts?: TreeNodeValueOptions): TreeNodeValue;
|
||||
/**
|
||||
* Options passed to `parseSegment()`to control how a segment of a file path is parsed. e.g. in `/users/[id]`, `users`
|
||||
* and `[id]` are segments.
|
||||
*/
|
||||
interface ParseSegmentOptions {
|
||||
/**
|
||||
* Should we allow dot nesting in the param name. e.g. `users.[id]` will be parsed as `users/[id]` if this is `true`,
|
||||
* nesting. Note this only works for the `file` format.
|
||||
*
|
||||
* @default `true`
|
||||
*/
|
||||
dotNesting?: boolean;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/core/tree.d.ts
|
||||
interface TreeNodeOptions extends ResolvedOptions {
|
||||
treeNodeOptions?: TreeNodeValueOptions;
|
||||
}
|
||||
declare class TreeNode {
|
||||
/**
|
||||
* value of the node
|
||||
*/
|
||||
value: TreeNodeValue;
|
||||
/**
|
||||
* children of the node
|
||||
*/
|
||||
children: Map<string, TreeNode>;
|
||||
/**
|
||||
* Parent node.
|
||||
*/
|
||||
parent: TreeNode | undefined;
|
||||
/**
|
||||
* Plugin options taken into account by the tree.
|
||||
*/
|
||||
options: TreeNodeOptions;
|
||||
/**
|
||||
* Should this page import the page info
|
||||
*/
|
||||
hasDefinePage: boolean;
|
||||
/**
|
||||
* Creates a new tree node.
|
||||
*
|
||||
* @param options - TreeNodeOptions shared by all nodes
|
||||
* @param pathSegment - path segment of this node e.g. `users` or `:id`
|
||||
* @param parent
|
||||
*/
|
||||
constructor(options: TreeNodeOptions, pathSegment: string, parent?: TreeNode);
|
||||
/**
|
||||
* Adds a path to the tree. `path` cannot start with a `/`.
|
||||
*
|
||||
* @param path - path segment to insert. **It shouldn't contain the file extension**
|
||||
* @param filePath - file path, must be a file (not a folder)
|
||||
*/
|
||||
insert(path: string, filePath: string): TreeNode;
|
||||
/**
|
||||
* Adds a path that has already been parsed to the tree. `path` cannot start with a `/`. This method is similar to
|
||||
* `insert` but the path argument should be already parsed. e.g. `users/:id` for a file named `users/[id].vue`.
|
||||
*
|
||||
* @param path - path segment to insert, already parsed (e.g. users/:id)
|
||||
* @param filePath - file path, defaults to path for convenience and testing
|
||||
*/
|
||||
insertParsedPath(path: string, filePath?: string): TreeNode;
|
||||
/**
|
||||
* Saves a custom route block for a specific file path. The file path is used as a key. Some special file paths will
|
||||
* have a lower or higher priority.
|
||||
*
|
||||
* @param filePath - file path where the custom block is located
|
||||
* @param routeBlock - custom block to set
|
||||
*/
|
||||
setCustomRouteBlock(filePath: string, routeBlock: CustomRouteBlock | undefined): void;
|
||||
/**
|
||||
* Generator that yields all descendants without sorting.
|
||||
* Use with Array.from() for now, native .map() support in Node 22+.
|
||||
*/
|
||||
getChildrenDeep(): Generator<TreeNode>;
|
||||
/**
|
||||
* Comparator function for sorting TreeNodes.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static compare(a: TreeNode, b: TreeNode): number;
|
||||
/**
|
||||
* Get the children of this node sorted by their path.
|
||||
*/
|
||||
getChildrenSorted(): TreeNode[];
|
||||
/**
|
||||
* Calls {@link getChildrenDeep} and sorts the result by path in the end.
|
||||
*/
|
||||
getChildrenDeepSorted(): TreeNode[];
|
||||
/**
|
||||
* Delete and detach itself from the tree.
|
||||
*/
|
||||
delete(): void;
|
||||
/**
|
||||
* Remove a route from the tree. The path shouldn't start with a `/` but it can be a nested one. e.g. `foo/bar`.
|
||||
* The `path` should be relative to the page folder.
|
||||
*
|
||||
* @param path - path segment of the file
|
||||
*/
|
||||
remove(path: string): void;
|
||||
/**
|
||||
* Returns the route path of the node without parent paths. If the path was overridden, it returns the override.
|
||||
*/
|
||||
get path(): string;
|
||||
/**
|
||||
* Returns the route path of the node including parent paths.
|
||||
*/
|
||||
get fullPath(): string;
|
||||
get components(): {
|
||||
[k: string]: string;
|
||||
};
|
||||
/**
|
||||
* Returns the route name of the node. If the name was overridden, it returns the override.
|
||||
*/
|
||||
get name(): string | false;
|
||||
/**
|
||||
* Returns the meta property as an object.
|
||||
*/
|
||||
get metaAsObject(): Readonly<RouteMeta>;
|
||||
/**
|
||||
* Returns the JSON string of the meta object of the node. If the meta was overridden, it returns the override. If
|
||||
* there is no override, it returns an empty string.
|
||||
*/
|
||||
get meta(): string;
|
||||
get params(): TreeRouteParam[];
|
||||
/**
|
||||
* Returns wether this tree node is the root node of the tree.
|
||||
*
|
||||
* @returns true if the node is the root node
|
||||
*/
|
||||
isRoot(): this is PrefixTree;
|
||||
toString(): string;
|
||||
}
|
||||
/**
|
||||
* Creates a new prefix tree. This is meant to only be the root node. It has access to extra methods that only make
|
||||
* sense on the root node.
|
||||
*/
|
||||
declare class PrefixTree extends TreeNode {
|
||||
map: Map<string, TreeNode>;
|
||||
constructor(options: ResolvedOptions);
|
||||
insert(path: string, filePath: string): TreeNode;
|
||||
/**
|
||||
* Returns the tree node of the given file path.
|
||||
*
|
||||
* @param filePath - file path of the tree node to get
|
||||
*/
|
||||
getChild(filePath: string): TreeNode | undefined;
|
||||
/**
|
||||
* Removes the tree node of the given file path.
|
||||
*
|
||||
* @param filePath - file path of the tree node to remove
|
||||
*/
|
||||
removeChild(filePath: string): void;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/core/utils.d.ts
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
declare function getPascalCaseRouteName(node: TreeNode): string;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
declare function getFileBasedRouteName(node: TreeNode): string;
|
||||
//#endregion
|
||||
//#region src/core/extendRoutes.d.ts
|
||||
/**
|
||||
* A route node that can be modified by the user. The tree can be iterated to be traversed.
|
||||
* @example
|
||||
* ```js
|
||||
* [...node] // creates an array of all the children
|
||||
* for (const child of node) {
|
||||
* // do something with the child node
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
declare class EditableTreeNode {
|
||||
private node;
|
||||
constructor(node: TreeNode);
|
||||
/**
|
||||
* Remove and detach the current route node from the tree. Subsequently, its children will be removed as well.
|
||||
*/
|
||||
delete(): void;
|
||||
/**
|
||||
* Inserts a new route as a child of this route. This route cannot use `definePage()`. If it was meant to be included,
|
||||
* add it to the `routesFolder` option.
|
||||
*
|
||||
* @param path - path segment to insert. Note this is relative to the current route. **It shouldn't start with `/`**. If it does, it will be added to the root of the tree.
|
||||
* @param filePath - file path
|
||||
* @returns the new editable route node
|
||||
*/
|
||||
insert(path: string, filePath: string): EditableTreeNode;
|
||||
/**
|
||||
* Get an editable version of the parent node if it exists.
|
||||
*/
|
||||
get parent(): EditableTreeNode | undefined;
|
||||
/**
|
||||
* Return a Map of the files associated to the current route. The key of the map represents the name of the view (Vue
|
||||
* Router feature) while the value is the **resolved** file path.
|
||||
* By default, the name of the view is `default`.
|
||||
*/
|
||||
get components(): Map<string, string>;
|
||||
/**
|
||||
* Alias for `route.components.get('default')`.
|
||||
*/
|
||||
get component(): string | undefined;
|
||||
/**
|
||||
* Name of the route. Note that **all routes are named** but when the final `routes` array is generated, routes
|
||||
* without a `component` will not include their `name` property to avoid accidentally navigating to them and display
|
||||
* nothing.
|
||||
* @see {@link isPassThrough}
|
||||
*/
|
||||
get name(): string | false;
|
||||
/**
|
||||
* Override the name of the route.
|
||||
*/
|
||||
set name(name: string | undefined);
|
||||
/**
|
||||
* Whether the route is a pass-through route. A pass-through route is a route that does not have a component and is
|
||||
* used to group other routes under the same prefix `path` and/or `meta` properties.
|
||||
*/
|
||||
get isPassThrough(): boolean;
|
||||
/**
|
||||
* Meta property of the route as an object. Note this property is readonly and will be serialized as JSON. It won't contain the meta properties defined with `definePage()` as it could contain expressions **but it does contain the meta properties defined with `<route>` blocks**.
|
||||
*/
|
||||
get meta(): Readonly<RouteMeta>;
|
||||
/**
|
||||
* Override the meta property of the route. This will discard any other meta property defined with `<route>` blocks or
|
||||
* through other means. If you want to keep the existing meta properties, use `addToMeta`.
|
||||
* @see {@link addToMeta}
|
||||
*/
|
||||
set meta(meta: RouteMeta);
|
||||
/**
|
||||
* Add meta properties to the route keeping the existing ones. The passed object will be deeply merged with the
|
||||
* existing meta object if any. Note that the meta property is later on serialized as JSON so you can't pass functions
|
||||
* or any other non-serializable value.
|
||||
*/
|
||||
addToMeta(meta: Partial<RouteMeta>): void;
|
||||
/**
|
||||
* Path of the route without parent paths.
|
||||
*/
|
||||
get path(): string;
|
||||
/**
|
||||
* Override the path of the route. You must ensure `params` match with the existing path.
|
||||
*/
|
||||
set path(path: string);
|
||||
/**
|
||||
* Alias of the route.
|
||||
*/
|
||||
get alias(): string | string[] | undefined;
|
||||
/**
|
||||
* Add an alias to the route.
|
||||
*
|
||||
* @param alias - Alias to add to the route
|
||||
*/
|
||||
addAlias(alias: CustomRouteBlock['alias']): void;
|
||||
/**
|
||||
* Array of the route params and all of its parent's params. Note that changing the params will not update the path,
|
||||
* you need to update both.
|
||||
*/
|
||||
get params(): TreeRouteParam[];
|
||||
/**
|
||||
* Path of the route including parent paths.
|
||||
*/
|
||||
get fullPath(): string;
|
||||
/**
|
||||
* Computes an array of EditableTreeNode from the current node. Differently from iterating over the tree, this method
|
||||
* **only returns direct children**.
|
||||
*/
|
||||
get children(): EditableTreeNode[];
|
||||
/**
|
||||
* DFS traversal of the tree.
|
||||
* @example
|
||||
* ```ts
|
||||
* for (const node of tree) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
traverseDFS(): Generator<EditableTreeNode, void, unknown>;
|
||||
[Symbol.iterator](): Generator<EditableTreeNode, void, unknown>;
|
||||
/**
|
||||
* BFS traversal of the tree as a generator.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* for (const node of tree) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
traverseBFS(): Generator<EditableTreeNode, void, unknown>;
|
||||
}
|
||||
//#endregion
|
||||
//#region src/utils/index.d.ts
|
||||
/**
|
||||
* Maybe a promise maybe not
|
||||
* @internal
|
||||
*/
|
||||
type _Awaitable<T> = T | PromiseLike<T>;
|
||||
/**
|
||||
* Creates a union type that still allows autocompletion for strings.
|
||||
*@internal
|
||||
*/
|
||||
//#endregion
|
||||
//#region src/options.d.ts
|
||||
/**
|
||||
* Options for a routes folder.
|
||||
*/
|
||||
interface RoutesFolderOption {
|
||||
/**
|
||||
* Folder to scan files that should be used for routes. **Cannot be a glob**, use the `path`, `filePatterns`, and
|
||||
* `exclude` options to filter out files. This section will **be removed** from the resulting path.
|
||||
*/
|
||||
src: string;
|
||||
/**
|
||||
* Prefix to add to the route path **as is**. Defaults to `''`. Can also be a function
|
||||
* to reuse parts of the filepath, in that case you should return a **modified version of the filepath**.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* {
|
||||
* src: 'src/pages',
|
||||
* // this is equivalent to the default behavior
|
||||
* path: (file) => file.slice(file.lastIndexOf('src/pages') + 'src/pages'.length
|
||||
* },
|
||||
* {
|
||||
* src: 'src/features',
|
||||
* // match all files (note the \ is not needed in real code)
|
||||
* filePatterns: '*/pages/**\/',
|
||||
* path: (file) => {
|
||||
* const prefix = 'src/features'
|
||||
* // remove the everything before src/features and removes /pages
|
||||
* // /src/features/feature1/pages/index.vue -> feature1/index.vue
|
||||
* return file.slice(file.lastIndexOf(prefix) + prefix.length + 1).replace('/pages', '')
|
||||
* },
|
||||
* },
|
||||
* {
|
||||
* src: 'src/docs',
|
||||
* // adds a prefix with a param
|
||||
* path: 'docs/[lang]/',
|
||||
* },
|
||||
* ```
|
||||
*/
|
||||
path?: string | ((filepath: string) => string);
|
||||
/**
|
||||
* Allows to override the global `filePattern` option for this folder. It can also extend the global values by passing
|
||||
* a function that returns an array.
|
||||
*/
|
||||
filePatterns?: _OverridableOption<string[], string | string[]>;
|
||||
/**
|
||||
* Allows to override the global `exclude` option for this folder. It can
|
||||
* also extend the global values by passing a function that returns an array.
|
||||
*/
|
||||
exclude?: _OverridableOption<string[], string | string[]>;
|
||||
/**
|
||||
* Allows to override the global `extensions` option for this folder. It can
|
||||
* also extend the global values by passing a function that returns an array.
|
||||
* The provided extensions are removed from the final route. For example,
|
||||
* `.page.vue` allows to suffix all pages with `.page.vue` and remove it from
|
||||
* the route name.
|
||||
*/
|
||||
extensions?: _OverridableOption<string[]>;
|
||||
}
|
||||
/**
|
||||
* Normalized options for a routes folder.
|
||||
*/
|
||||
interface RoutesFolderOptionResolved extends RoutesFolderOption {
|
||||
path: string | ((filepath: string) => string);
|
||||
/**
|
||||
* Final glob pattern to match files in the folder.
|
||||
*/
|
||||
pattern: string[];
|
||||
filePatterns: string[];
|
||||
exclude: string[];
|
||||
extensions: string[];
|
||||
}
|
||||
type _OverridableOption<T, AllowedTypes = T> = AllowedTypes | ((existing: T) => T);
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
declare function resolveOverridableOption<T>(defaultValue: T, value?: _OverridableOption<T, T>): T;
|
||||
type _RoutesFolder = string | RoutesFolderOption;
|
||||
type RoutesFolder = _RoutesFolder[] | _RoutesFolder;
|
||||
/**
|
||||
* unplugin-vue-router plugin options.
|
||||
*/
|
||||
interface Options {
|
||||
/**
|
||||
* Extensions of files to be considered as pages. Cannot be empty. This allows to strip a
|
||||
* bigger part of the filename e.g. `index.page.vue` -> `index` if an extension of `.page.vue` is provided.
|
||||
* @default `['.vue']`
|
||||
*/
|
||||
extensions?: string[];
|
||||
/**
|
||||
* Folder(s) to scan for files and generate routes. Can also be an array if you want to add multiple
|
||||
* folders, or an object if you want to define a route prefix. Supports glob patterns but must be a folder, use
|
||||
* `extensions` and `exclude` to filter files.
|
||||
*
|
||||
* @default `"src/pages"`
|
||||
*/
|
||||
routesFolder?: RoutesFolder;
|
||||
/**
|
||||
* Array of `picomatch` globs to ignore. Note the globs are relative to the cwd, so avoid writing
|
||||
* something like `['ignored']` to match folders named that way, instead provide a path similar to the `routesFolder`:
|
||||
* `['src/pages/ignored/**']` or use `['**/ignored']` to match every folder named `ignored`.
|
||||
* @default `[]`
|
||||
*/
|
||||
exclude?: string[] | string;
|
||||
/**
|
||||
* Pattern to match files in the `routesFolder`. Defaults to `**/*` plus a combination of all the possible extensions,
|
||||
* e.g. `**/*.{vue,md}` if `extensions` is set to `['.vue', '.md']`. This is relative to the {@link RoutesFolderOption['src']} and
|
||||
* @default `['**/*']`
|
||||
*/
|
||||
filePatterns?: string[] | string;
|
||||
/**
|
||||
* Method to generate the name of a route. It's recommended to keep the default value to guarantee a consistent,
|
||||
* unique, and predictable naming.
|
||||
*/
|
||||
getRouteName?: (node: TreeNode) => string;
|
||||
/**
|
||||
* Allows to extend a route by modifying its node, adding children, or even deleting it. This will be invoked once for
|
||||
* each route.
|
||||
*
|
||||
* @param route - {@link EditableTreeNode} of the route to extend
|
||||
*/
|
||||
extendRoute?: (route: EditableTreeNode) => _Awaitable<void>;
|
||||
/**
|
||||
* Allows to do some changes before writing the files. This will be invoked **every time** the files need to be written.
|
||||
*
|
||||
* @param rootRoute - {@link EditableTreeNode} of the root route
|
||||
*/
|
||||
beforeWriteFiles?: (rootRoute: EditableTreeNode) => _Awaitable<void>;
|
||||
/**
|
||||
* Defines how page components should be imported. Defaults to dynamic imports to enable lazy loading of pages.
|
||||
* @default `'async'`
|
||||
*/
|
||||
importMode?: 'sync' | 'async' | ((filepath: string) => 'sync' | 'async');
|
||||
/**
|
||||
* Root of the project. All paths are resolved relatively to this one.
|
||||
* @default `process.cwd()`
|
||||
*/
|
||||
root?: string;
|
||||
/**
|
||||
* Language for `<route>` blocks in SFC files.
|
||||
* @default `'json5'`
|
||||
*/
|
||||
routeBlockLang?: 'yaml' | 'yml' | 'json5' | 'json';
|
||||
/**
|
||||
* Should we generate d.ts files or ont. Defaults to `true` if `typescript` is installed. Can be set to a string of
|
||||
* the filepath to write the d.ts files to. By default it will generate a file named `typed-router.d.ts`.
|
||||
* @default `true`
|
||||
*/
|
||||
dts?: boolean | string;
|
||||
/**
|
||||
* Allows inspection by vite-plugin-inspect by not adding the leading `\0` to the id of virtual modules.
|
||||
* @internal
|
||||
*/
|
||||
_inspect?: boolean;
|
||||
/**
|
||||
* Activates debug logs.
|
||||
*/
|
||||
logs?: boolean;
|
||||
/**
|
||||
* @inheritDoc ParseSegmentOptions
|
||||
*/
|
||||
pathParser?: ParseSegmentOptions;
|
||||
/**
|
||||
* Whether to watch the files for changes.
|
||||
*
|
||||
* Defaults to `true` unless the `CI` environment variable is set.
|
||||
*
|
||||
* @default `!process.env.CI`
|
||||
*/
|
||||
watch?: boolean;
|
||||
/**
|
||||
* Experimental options. **Warning**: these can change or be removed at any time, even it patch releases. Keep an eye
|
||||
* on the Changelog.
|
||||
*/
|
||||
experimental?: {
|
||||
/**
|
||||
* (Vite only). File paths or globs where loaders are exported. This will be used to filter out imported loaders and
|
||||
* automatically re export them in page components. You can for example set this to `'src/loaders/**\/*'` (without
|
||||
* the backslash) to automatically re export any imported variable from files in the `src/loaders` folder within a
|
||||
* page component.
|
||||
*/
|
||||
autoExportsDataLoaders?: string | string[];
|
||||
};
|
||||
}
|
||||
declare const DEFAULT_OPTIONS: {
|
||||
extensions: string[];
|
||||
exclude: never[];
|
||||
routesFolder: string;
|
||||
filePatterns: string[];
|
||||
routeBlockLang: "json5";
|
||||
getRouteName: typeof getFileBasedRouteName;
|
||||
importMode: "async";
|
||||
root: string;
|
||||
dts: boolean;
|
||||
logs: false;
|
||||
_inspect: false;
|
||||
pathParser: {
|
||||
dotNesting: true;
|
||||
};
|
||||
watch: boolean;
|
||||
experimental: {};
|
||||
};
|
||||
interface ServerContext {
|
||||
invalidate: (module: string) => void;
|
||||
updateRoutes: () => Promise<void>;
|
||||
reload: () => void;
|
||||
}
|
||||
/**
|
||||
* Normalize user options with defaults and resolved paths.
|
||||
*
|
||||
* @param options - user provided options
|
||||
* @returns normalized options
|
||||
*/
|
||||
declare function resolveOptions(options: Options): {
|
||||
experimental: {
|
||||
autoExportsDataLoaders?: string | string[];
|
||||
};
|
||||
routesFolder: {
|
||||
src: string;
|
||||
filePatterns: string[] | ((existing: string[]) => string[]) | undefined;
|
||||
exclude: string[] | ((existing: string[]) => string[]) | undefined;
|
||||
/**
|
||||
* Prefix to add to the route path **as is**. Defaults to `''`. Can also be a function
|
||||
* to reuse parts of the filepath, in that case you should return a **modified version of the filepath**.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* {
|
||||
* src: 'src/pages',
|
||||
* // this is equivalent to the default behavior
|
||||
* path: (file) => file.slice(file.lastIndexOf('src/pages') + 'src/pages'.length
|
||||
* },
|
||||
* {
|
||||
* src: 'src/features',
|
||||
* // match all files (note the \ is not needed in real code)
|
||||
* filePatterns: '*/pages/**\/',
|
||||
* path: (file) => {
|
||||
* const prefix = 'src/features'
|
||||
* // remove the everything before src/features and removes /pages
|
||||
* // /src/features/feature1/pages/index.vue -> feature1/index.vue
|
||||
* return file.slice(file.lastIndexOf(prefix) + prefix.length + 1).replace('/pages', '')
|
||||
* },
|
||||
* },
|
||||
* {
|
||||
* src: 'src/docs',
|
||||
* // adds a prefix with a param
|
||||
* path: 'docs/[lang]/',
|
||||
* },
|
||||
* ```
|
||||
*/
|
||||
path?: string | ((filepath: string) => string);
|
||||
/**
|
||||
* Allows to override the global `extensions` option for this folder. It can
|
||||
* also extend the global values by passing a function that returns an array.
|
||||
* The provided extensions are removed from the final route. For example,
|
||||
* `.page.vue` allows to suffix all pages with `.page.vue` and remove it from
|
||||
* the route name.
|
||||
*/
|
||||
extensions?: _OverridableOption<string[]>;
|
||||
}[];
|
||||
filePatterns: string[];
|
||||
exclude: string[];
|
||||
extensions: string[];
|
||||
getRouteName: typeof getFileBasedRouteName;
|
||||
/**
|
||||
* Allows to extend a route by modifying its node, adding children, or even deleting it. This will be invoked once for
|
||||
* each route.
|
||||
*
|
||||
* @param route - {@link EditableTreeNode} of the route to extend
|
||||
*/
|
||||
extendRoute?: (route: EditableTreeNode) => _Awaitable<void>;
|
||||
/**
|
||||
* Allows to do some changes before writing the files. This will be invoked **every time** the files need to be written.
|
||||
*
|
||||
* @param rootRoute - {@link EditableTreeNode} of the root route
|
||||
*/
|
||||
beforeWriteFiles?: (rootRoute: EditableTreeNode) => _Awaitable<void>;
|
||||
importMode: "sync" | "async" | ((filepath: string) => "sync" | "async");
|
||||
root: string;
|
||||
routeBlockLang: "yaml" | "yml" | "json5" | "json";
|
||||
dts: boolean | string;
|
||||
_inspect: boolean;
|
||||
logs: boolean;
|
||||
pathParser: ParseSegmentOptions;
|
||||
watch: boolean;
|
||||
};
|
||||
type ResolvedOptions = ReturnType<typeof resolveOptions>;
|
||||
/**
|
||||
* Merge all the possible extensions as an array of unique values
|
||||
* @param options - user provided options
|
||||
* @internal
|
||||
*/
|
||||
declare function mergeAllExtensions(options: ResolvedOptions): string[];
|
||||
//#endregion
|
||||
export { DEFAULT_OPTIONS, EditableTreeNode, Options, ResolvedOptions, RoutesFolder, RoutesFolderOption, RoutesFolderOptionResolved, ServerContext, TreeNode, TreeNodeValueParam, TreeNodeValueStatic, _OverridableOption, _RoutesFolder, createTreeNodeValue, getFileBasedRouteName, getPascalCaseRouteName, mergeAllExtensions, resolveOptions, resolveOverridableOption };
|
||||
Generated
Vendored
+274
@@ -0,0 +1,274 @@
|
||||
import { pascalCase } from "scule";
|
||||
import { resolve } from "pathe";
|
||||
import { isPackageExists } from "local-pkg";
|
||||
|
||||
//#region src/core/utils.ts
|
||||
function warn(msg, type = "warn") {
|
||||
console[type](`⚠️ [unplugin-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$1, extensions) {
|
||||
for (const extension of extensions) {
|
||||
const lastDot = path$1.endsWith(extension) ? -extension.length : 0;
|
||||
if (lastDot < 0) return path$1.slice(0, lastDot);
|
||||
}
|
||||
return path$1;
|
||||
}
|
||||
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 = /\/$/;
|
||||
function joinPath(...paths) {
|
||||
let result = "";
|
||||
for (const path$1 of paths) result = result.replace(TRAILING_SLASH_RE, "") + (path$1 && "/" + path$1.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") {
|
||||
const newAlias = [];
|
||||
merged[key] = newAlias.concat(a.alias || [], b.alias || []);
|
||||
} else if (key === "meta") merged[key] = mergeDeep(a[key] || {}, b[key] || {});
|
||||
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: path$1 = "", extensions }, filePath) {
|
||||
return trimExtension(typeof path$1 === "string" ? path$1 + filePath.slice(src.length + 1) : path$1(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$1, importEntry) {
|
||||
if (!this.map.has(path$1)) this.map.set(path$1, /* @__PURE__ */ new Map());
|
||||
const imports = this.map.get(path$1);
|
||||
if (typeof importEntry === "string") imports.set(importEntry, importEntry);
|
||||
else imports.set(importEntry.as || importEntry.name, importEntry.name);
|
||||
return this;
|
||||
}
|
||||
addDefault(path$1, as) {
|
||||
return this.add(path$1, {
|
||||
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$1) {
|
||||
if (!this.map.has(path$1)) return [];
|
||||
return Array.from(this.map.get(path$1)).map(([as, name]) => ({
|
||||
as: as || name,
|
||||
name
|
||||
}));
|
||||
}
|
||||
toString() {
|
||||
let importStatements = "";
|
||||
for (const [path$1, imports] of this.map) {
|
||||
if (!imports.size) continue;
|
||||
if (imports.size === 1) {
|
||||
const [[importName, maybeDefault]] = [...imports.entries()];
|
||||
if (maybeDefault === "default") {
|
||||
importStatements += `import ${importName} from '${path$1}'\n`;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
importStatements += `import { ${Array.from(imports).map(([as, name]) => as === name ? name : `${name} as ${as}`).join(", ")} } from '${path$1}'\n`;
|
||||
}
|
||||
return importStatements;
|
||||
}
|
||||
get size() {
|
||||
return this.map.size;
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
//#region src/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
|
||||
*/
|
||||
function resolveOverridableOption(defaultValue, value) {
|
||||
return typeof value === "function" ? value(defaultValue) : value ?? defaultValue;
|
||||
}
|
||||
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 experimental = { ...options.experimental };
|
||||
if (experimental.autoExportsDataLoaders) experimental.autoExportsDataLoaders = (Array.isArray(experimental.autoExportsDataLoaders) ? experimental.autoExportsDataLoaders : [experimental.autoExportsDataLoaders]).map((path$1) => resolve(root, path$1));
|
||||
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 { DEFAULT_OPTIONS, ImportsMap, appendExtensionListToPattern, asRoutePath, getFileBasedRouteName, getPascalCaseRouteName, joinPath, logTree, mergeAllExtensions, mergeRouteRecordOverride, resolveOptions, resolveOverridableOption, throttle, warn };
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
const require_options = require('./options-BirY6CFZ.cjs');
|
||||
|
||||
exports.DEFAULT_OPTIONS = require_options.DEFAULT_OPTIONS;
|
||||
exports.mergeAllExtensions = require_options.mergeAllExtensions;
|
||||
exports.resolveOptions = require_options.resolveOptions;
|
||||
exports.resolveOverridableOption = require_options.resolveOverridableOption;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import { DEFAULT_OPTIONS, Options, ResolvedOptions, RoutesFolder, RoutesFolderOption, RoutesFolderOptionResolved, ServerContext, _OverridableOption, _RoutesFolder, mergeAllExtensions, resolveOptions, resolveOverridableOption } from "./options-DN4Qs-Nr.cjs";
|
||||
export { DEFAULT_OPTIONS, Options, ResolvedOptions, RoutesFolder, RoutesFolderOption, RoutesFolderOptionResolved, ServerContext, _OverridableOption, _RoutesFolder, mergeAllExtensions, resolveOptions, resolveOverridableOption };
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import { DEFAULT_OPTIONS, Options, ResolvedOptions, RoutesFolder, RoutesFolderOption, RoutesFolderOptionResolved, ServerContext, _OverridableOption, _RoutesFolder, mergeAllExtensions, resolveOptions, resolveOverridableOption } from "./options-PFbkwBvS.js";
|
||||
export { DEFAULT_OPTIONS, Options, ResolvedOptions, RoutesFolder, RoutesFolderOption, RoutesFolderOptionResolved, ServerContext, _OverridableOption, _RoutesFolder, mergeAllExtensions, resolveOptions, resolveOverridableOption };
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import { DEFAULT_OPTIONS, mergeAllExtensions, resolveOptions, resolveOverridableOption } from "./options-vQOEqZ01.js";
|
||||
|
||||
export { DEFAULT_OPTIONS, mergeAllExtensions, resolveOptions, resolveOverridableOption };
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
require('./options-BirY6CFZ.cjs');
|
||||
const require_src = require('./src-DB0pAxuH.cjs');
|
||||
|
||||
//#region src/rollup.ts
|
||||
var rollup_default = require_src.src_default.rollup;
|
||||
|
||||
//#endregion
|
||||
module.exports = rollup_default;
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import { Options } from "./options-DN4Qs-Nr.cjs";
|
||||
import * as rollup1 from "rollup";
|
||||
|
||||
//#region src/rollup.d.ts
|
||||
declare const _default: (options?: Options | undefined) => rollup1.Plugin<any> | rollup1.Plugin<any>[];
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import { Options } from "./options-PFbkwBvS.js";
|
||||
import * as rollup7 from "rollup";
|
||||
|
||||
//#region src/rollup.d.ts
|
||||
declare const _default: (options?: Options | undefined) => rollup7.Plugin<any> | rollup7.Plugin<any>[];
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import "./options-vQOEqZ01.js";
|
||||
import { src_default } from "./src-BVnnbDr_.js";
|
||||
|
||||
//#region src/rollup.ts
|
||||
var rollup_default = src_default.rollup;
|
||||
|
||||
//#endregion
|
||||
export { rollup_default as default };
|
||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
|
||||
//#region src/runtime.ts
|
||||
/**
|
||||
* Defines properties of the route for the current page component.
|
||||
*
|
||||
* @param route - route information to be added to this page
|
||||
* @deprecated - use `definePage` instead
|
||||
*/
|
||||
const _definePage = (route) => route;
|
||||
/**
|
||||
* Defines properties of the route for the current page component.
|
||||
*
|
||||
* @param route - route information to be added to this page
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
exports._definePage = _definePage;
|
||||
exports._mergeRouteRecord = _mergeRouteRecord;
|
||||
exports.definePage = definePage;
|
||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
import { RouteRecordRaw } from "vue-router";
|
||||
|
||||
//#region src/runtime.d.ts
|
||||
|
||||
/**
|
||||
* Defines properties of the route for the current page component.
|
||||
*
|
||||
* @param route - route information to be added to this page
|
||||
* @deprecated - use `definePage` instead
|
||||
*/
|
||||
declare const _definePage: (route: DefinePage) => DefinePage;
|
||||
/**
|
||||
* Defines properties of the route for the current page component.
|
||||
*
|
||||
* @param route - route information to be added to this page
|
||||
*/
|
||||
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;
|
||||
}
|
||||
//#endregion
|
||||
export { DefinePage, _definePage, _mergeRouteRecord, definePage };
|
||||
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
import { RouteRecordRaw } from "vue-router";
|
||||
|
||||
//#region src/runtime.d.ts
|
||||
|
||||
/**
|
||||
* Defines properties of the route for the current page component.
|
||||
*
|
||||
* @param route - route information to be added to this page
|
||||
* @deprecated - use `definePage` instead
|
||||
*/
|
||||
declare const _definePage: (route: DefinePage) => DefinePage;
|
||||
/**
|
||||
* Defines properties of the route for the current page component.
|
||||
*
|
||||
* @param route - route information to be added to this page
|
||||
*/
|
||||
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;
|
||||
}
|
||||
//#endregion
|
||||
export { DefinePage, _definePage, _mergeRouteRecord, definePage };
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
//#region src/runtime.ts
|
||||
/**
|
||||
* Defines properties of the route for the current page component.
|
||||
*
|
||||
* @param route - route information to be added to this page
|
||||
* @deprecated - use `definePage` instead
|
||||
*/
|
||||
const _definePage = (route) => route;
|
||||
/**
|
||||
* Defines properties of the route for the current page component.
|
||||
*
|
||||
* @param route - route information to be added to this page
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
export { _definePage, _mergeRouteRecord, definePage };
|
||||
Generated
Vendored
+1688
File diff suppressed because it is too large
Load diff
Generated
Vendored
+1723
File diff suppressed because it is too large
Load diff
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export { };
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
export { };
|
||||
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
import { EditableTreeNode, Options, TreeNode, TreeNodeValueParam, TreeNodeValueStatic } from "./options-DN4Qs-Nr.cjs";
|
||||
import "./types-CuECKBwm.cjs";
|
||||
export { EditableTreeNode, Options, TreeNode, TreeNodeValueParam, TreeNodeValueStatic };
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import { EditableTreeNode, Options, TreeNode, TreeNodeValueParam, TreeNodeValueStatic } from "./options-PFbkwBvS.js";
|
||||
import "./types-BaFiruHW.js";
|
||||
export { EditableTreeNode, Options, TreeNode, TreeNodeValueParam, TreeNodeValueStatic };
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
require('./options-BirY6CFZ.cjs');
|
||||
const require_src = require('./src-DB0pAxuH.cjs');
|
||||
|
||||
//#region src/vite.ts
|
||||
var vite_default = require_src.src_default.vite;
|
||||
|
||||
//#endregion
|
||||
module.exports = vite_default;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { Options } from "./options-DN4Qs-Nr.cjs";
|
||||
import * as vite4 from "vite";
|
||||
|
||||
//#region src/vite.d.ts
|
||||
declare const _default: (options?: Options | undefined) => vite4.Plugin<any> | vite4.Plugin<any>[];
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { Options } from "./options-PFbkwBvS.js";
|
||||
import * as vite4 from "vite";
|
||||
|
||||
//#region src/vite.d.ts
|
||||
declare const _default: (options?: Options | undefined) => vite4.Plugin<any> | vite4.Plugin<any>[];
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import "./options-vQOEqZ01.js";
|
||||
import { src_default } from "./src-BVnnbDr_.js";
|
||||
|
||||
//#region src/vite.ts
|
||||
var vite_default = src_default.vite;
|
||||
|
||||
//#endregion
|
||||
export { vite_default as default };
|
||||
Generated
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
//#region rolldown:runtime
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
||||
key = keys[i];
|
||||
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
||||
get: ((k) => from[k]).bind(null, key),
|
||||
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
||||
});
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
||||
value: mod,
|
||||
enumerable: true
|
||||
}) : target, mod));
|
||||
|
||||
//#endregion
|
||||
|
||||
Object.defineProperty(exports, '__toESM', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return __toESM;
|
||||
}
|
||||
});
|
||||
Generated
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
||||
const __vue_language_core = require_chunk.__toESM(require("@vue/language-core"));
|
||||
const muggle_string = require_chunk.__toESM(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://raw.githubusercontent.com/posva/unplugin-vue-router/main/route.schema.json\",");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
var sfc_route_blocks_default = plugin;
|
||||
|
||||
//#endregion
|
||||
module.exports = sfc_route_blocks_default;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import { VueLanguagePlugin } from "@vue/language-core";
|
||||
|
||||
//#region src/volar/entries/sfc-route-blocks.d.ts
|
||||
declare const plugin: VueLanguagePlugin;
|
||||
//#endregion
|
||||
export { plugin as default };
|
||||
Generated
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
||||
const muggle_string = require_chunk.__toESM(require("muggle-string"));
|
||||
const pathe = require_chunk.__toESM(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 getCodes - function that computes the code to add to the VLS context.
|
||||
*/
|
||||
function augmentVlsCtx(content, getCodes) {
|
||||
let from = -1;
|
||||
let to = -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 && code === `;\n`) {
|
||||
to = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (to === -1) return;
|
||||
content.splice(to, 0, getCodes());
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#region src/volar/entries/sfc-typed-router.ts
|
||||
const plugin = (ctx) => {
|
||||
const RE = {
|
||||
USE_ROUTE: {
|
||||
BEFORE_PARENTHESES: /(?<=useRoute)(\s*)(?=\(\))/g,
|
||||
BEFORE: /(?=useRoute(\s*)\(\))/g,
|
||||
AFTER: /(?<=useRoute(\s*)\(\))/g
|
||||
},
|
||||
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 relativeFilePath = ctx.compilerOptions.baseUrl ? (0, pathe.relative)(ctx.compilerOptions.baseUrl, fileName) : fileName;
|
||||
const useRouteNameType = `import('vue-router/auto-routes')._RouteNamesForFilePath<'${relativeFilePath}'>`;
|
||||
const useRouteNameTypeParam = `<${useRouteNameType}>`;
|
||||
const typedCall = `useRoute${useRouteNameTypeParam}`;
|
||||
if (embeddedCode.id.startsWith("script_ts")) (0, muggle_string.replaceAll)(embeddedCode.content, RE.USE_ROUTE.BEFORE_PARENTHESES, useRouteNameTypeParam);
|
||||
else if (embeddedCode.id.startsWith("script_js")) {
|
||||
(0, muggle_string.replaceAll)(embeddedCode.content, RE.USE_ROUTE.BEFORE, `(`);
|
||||
(0, muggle_string.replaceAll)(embeddedCode.content, RE.USE_ROUTE.AFTER, ` as ReturnType<typeof ${typedCall}>)`);
|
||||
}
|
||||
const contentStr = (0, muggle_string.toString)(embeddedCode.content);
|
||||
const vlsCtxAugmentations = [];
|
||||
if (contentStr.match(RE.DOLLAR_ROUTE.VLS_CTX)) vlsCtxAugmentations.push(`$route: ReturnType<typeof ${typedCall}>;`);
|
||||
if (vlsCtxAugmentations.length > 0) augmentVlsCtx(embeddedCode.content, () => ` & {
|
||||
${vlsCtxAugmentations.join("\n ")}
|
||||
}`);
|
||||
}
|
||||
};
|
||||
};
|
||||
var sfc_typed_router_default = plugin;
|
||||
|
||||
//#endregion
|
||||
module.exports = sfc_typed_router_default;
|
||||
Generated
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
import { VueLanguagePlugin } from "@vue/language-core";
|
||||
|
||||
//#region src/volar/entries/sfc-typed-router.d.ts
|
||||
declare const plugin: VueLanguagePlugin;
|
||||
//#endregion
|
||||
export { plugin as default };
|
||||
Generated
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
require('./options-BirY6CFZ.cjs');
|
||||
const require_src = require('./src-DB0pAxuH.cjs');
|
||||
|
||||
//#region src/webpack.ts
|
||||
var webpack_default = require_src.src_default.webpack;
|
||||
|
||||
//#endregion
|
||||
module.exports = webpack_default;
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import { Options } from "./options-DN4Qs-Nr.cjs";
|
||||
import * as webpack7 from "webpack";
|
||||
|
||||
//#region src/webpack.d.ts
|
||||
declare const _default: (options?: Options | undefined) => webpack7.WebpackPluginInstance;
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import { Options } from "./options-PFbkwBvS.js";
|
||||
import * as webpack1 from "webpack";
|
||||
|
||||
//#region src/webpack.d.ts
|
||||
declare const _default: (options?: Options | undefined) => webpack1.WebpackPluginInstance;
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import "./options-vQOEqZ01.js";
|
||||
import { src_default } from "./src-BVnnbDr_.js";
|
||||
|
||||
//#region src/webpack.ts
|
||||
var webpack_default = src_default.webpack;
|
||||
|
||||
//#endregion
|
||||
export { webpack_default as default };
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
{
|
||||
"name": "unplugin-vue-router",
|
||||
"version": "0.15.0",
|
||||
"type": "module",
|
||||
"description": "File based typed routing for Vue Router",
|
||||
"keywords": [
|
||||
"unplugin",
|
||||
"vite",
|
||||
"webpack",
|
||||
"rollup",
|
||||
"vue-router",
|
||||
"pages",
|
||||
"filesystem",
|
||||
"types",
|
||||
"typed",
|
||||
"vue",
|
||||
"nuxt",
|
||||
"router"
|
||||
],
|
||||
"homepage": "https://uvr.esm.is",
|
||||
"bugs": {
|
||||
"url": "https://github.com/posva/unplugin-vue-router/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/posva/unplugin-vue-router.git"
|
||||
},
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"./vite": {
|
||||
"import": "./dist/vite.js",
|
||||
"require": "./dist/vite.cjs"
|
||||
},
|
||||
"./webpack": {
|
||||
"import": "./dist/webpack.js",
|
||||
"require": "./dist/webpack.cjs"
|
||||
},
|
||||
"./rollup": {
|
||||
"import": "./dist/rollup.js",
|
||||
"require": "./dist/rollup.cjs"
|
||||
},
|
||||
"./esbuild": {
|
||||
"import": "./dist/esbuild.js",
|
||||
"require": "./dist/esbuild.cjs"
|
||||
},
|
||||
"./options": {
|
||||
"import": "./dist/options.js",
|
||||
"require": "./dist/options.cjs"
|
||||
},
|
||||
"./runtime": {
|
||||
"import": "./dist/runtime.js",
|
||||
"require": "./dist/runtime.cjs"
|
||||
},
|
||||
"./types": {
|
||||
"types": {
|
||||
"import": "./dist/types.d.ts",
|
||||
"require": "./dist/types.d.cts"
|
||||
}
|
||||
},
|
||||
"./data-loaders": {
|
||||
"import": "./dist/data-loaders/index.js",
|
||||
"require": "./dist/data-loaders/index.cjs"
|
||||
},
|
||||
"./data-loaders/basic": {
|
||||
"import": "./dist/data-loaders/basic.js",
|
||||
"require": "./dist/data-loaders/basic.cjs"
|
||||
},
|
||||
"./data-loaders/pinia-colada": {
|
||||
"import": "./dist/data-loaders/pinia-colada.js",
|
||||
"require": "./dist/data-loaders/pinia-colada.cjs"
|
||||
},
|
||||
"./volar/sfc-route-blocks": {
|
||||
"require": "./dist/volar/sfc-route-blocks.cjs"
|
||||
},
|
||||
"./volar/sfc-typed-router": {
|
||||
"require": "./dist/volar/sfc-typed-router.cjs"
|
||||
},
|
||||
"./client": {
|
||||
"types": "./client.d.ts"
|
||||
}
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"data-loaders": [
|
||||
"./dist/data-loaders/index.d.ts"
|
||||
],
|
||||
"data-loaders/basic": [
|
||||
"./dist/data-loaders/basic.d.ts"
|
||||
],
|
||||
"data-loaders/pinia-colada": [
|
||||
"./dist/data-loaders/pinia-colada.d.ts"
|
||||
],
|
||||
"*": [
|
||||
"./dist/*",
|
||||
"./*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"client.d.ts",
|
||||
"route.schema.json"
|
||||
],
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"commit-msg": "node scripts/verifyCommit.mjs"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,mjs,json,cjs,md}": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.ts?(x)": [
|
||||
"prettier --parser=typescript --write"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue-macros/common": "3.0.0-beta.16",
|
||||
"@vue/language-core": "^3.0.1",
|
||||
"ast-walker-scope": "^0.8.1",
|
||||
"chokidar": "^4.0.3",
|
||||
"json5": "^2.2.3",
|
||||
"local-pkg": "^1.1.1",
|
||||
"magic-string": "^0.30.17",
|
||||
"mlly": "^1.7.4",
|
||||
"muggle-string": "^0.4.1",
|
||||
"pathe": "^2.0.3",
|
||||
"picomatch": "^4.0.3",
|
||||
"scule": "^1.3.0",
|
||||
"tinyglobby": "^0.2.14",
|
||||
"unplugin": "^2.3.5",
|
||||
"unplugin-utils": "^0.2.4",
|
||||
"yaml": "^2.8.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/compiler-sfc": "^3.5.17",
|
||||
"vue-router": "^4.5.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"vue-router": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.28.1",
|
||||
"@pinia/colada": "^0.17.1",
|
||||
"@posva/prompts": "^2.4.4",
|
||||
"@shikijs/vitepress-twoslash": "3.8.0",
|
||||
"@tanstack/vue-query": "^5.83.0",
|
||||
"@types/node": "^22.16.4",
|
||||
"@types/picomatch": "^4.0.0",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"@vue/language-core": "^3.0.1",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"chalk": "^5.4.1",
|
||||
"conventional-changelog-cli": "^5.0.0",
|
||||
"execa": "^9.6.0",
|
||||
"firebase": "^12.0.0",
|
||||
"happy-dom": "^18.0.1",
|
||||
"lint-staged": "^16.1.2",
|
||||
"minimist": "^1.2.8",
|
||||
"nodemon": "^3.1.10",
|
||||
"p-series": "^3.0.0",
|
||||
"pinia": "^3.0.3",
|
||||
"prettier": "^3.6.2",
|
||||
"rimraf": "^6.0.1",
|
||||
"rollup": "^4.45.1",
|
||||
"semver": "^7.7.2",
|
||||
"ts-expect": "^1.3.0",
|
||||
"tsdown": "^0.12.9",
|
||||
"typescript": "^5.8.3",
|
||||
"unplugin-auto-import": "^19.3.0",
|
||||
"unplugin-vue-markdown": "^29.1.0",
|
||||
"vite": "^7.0.4",
|
||||
"vite-plugin-vue-devtools": "^7.7.7",
|
||||
"vitepress": "^1.6.3",
|
||||
"vitepress-plugin-llms": "^1.7.0",
|
||||
"vitest": "^3.2.4",
|
||||
"vue": "^3.5.17",
|
||||
"vue-router": "^4.5.1",
|
||||
"vue-router-mock": "^1.1.0",
|
||||
"vue-tsc": "^3.0.1",
|
||||
"vuefire": "^3.2.1",
|
||||
"webpack": "^5.100.2",
|
||||
"yorkie": "^2.0.0",
|
||||
"unplugin-vue-router": "0.15.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm run --stream '/^build:/'",
|
||||
"build:core": "tsdown",
|
||||
"build:runtime": "tsdown --config tsdown-runtime.config.ts",
|
||||
"dev": "pnpm run vitest --ui",
|
||||
"vitest": "vitest --typecheck",
|
||||
"docs": "vitepress dev docs",
|
||||
"docs:build": "vitepress build docs",
|
||||
"docs:preview": "vitepress preview docs",
|
||||
"lint": "prettier -c '{src,test,e2e,examples,playground}/**/*.{ts,vue}'",
|
||||
"play": "npm -C playground run dev",
|
||||
"play:build": "npm -C playground run build",
|
||||
"release": "node scripts/release.mjs",
|
||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1",
|
||||
"pretest": "pnpm run lint",
|
||||
"test": "pnpm run build && vitest --typecheck --coverage run && pnpm run docs:build"
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+25
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user