Skip to content

Commit

Permalink
refactor: remove /auto as much as possible
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Jun 21, 2024
1 parent 6044b94 commit 5f8a5a7
Show file tree
Hide file tree
Showing 18 changed files with 78 additions and 83 deletions.
12 changes: 12 additions & 0 deletions client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ declare module 'vue-router/auto-routes' {
/**
* Setups hot module replacement for routes.
* @param router - The router instance
* @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): void
}
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/eslint.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# ESlint

If you are not using auto imports, you will need to tell ESlint about `vue-router/auto` and `vue-router/auto-routes`. Add these lines to your eslint configuration:
If you are not using auto imports, you will need to tell ESlint about `vue-router/auto-routes`. Add these lines to your eslint configuration:

```json{3}
{
"settings": {
"import/core-modules": ["vue-router/auto", "vue-router/auto-routes"]
"import/core-modules": ["vue-router/auto-routes"]
}
}
```
6 changes: 2 additions & 4 deletions docs/guide/extending-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ It's possible to override the route configuration directly in the page component

### `definePage()`

You can modify and extend any page component with the `definePage()` macro from `vue-router/auto`. This is useful for adding meta information, or modifying the route object. If you have configured auto imports, you won't need to import `definePage` from `vue-router/auto` as it is already available.
You can modify and extend any page component with the `definePage()` macro. This is useful for adding meta information, or modifying the route object. It's globally available in Vue components but you can import it from `unplugin-vue-router/runtime` if needed.

```vue{2,4-9} twoslash
```vue{2-7} twoslash
<script setup lang="ts">
// ---cut-start---
import 'unplugin-vue-router/client'
Expand All @@ -53,8 +53,6 @@ export {}
// ---cut-end---
// @errors: 2322 2339
// @moduleResolution: bundler
import { definePage } from 'unplugin-vue-router/runtime'
definePage({
alias: ['/n/:name'],
meta: {
Expand Down
32 changes: 4 additions & 28 deletions docs/guide/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This plugin generates a `d.ts` file with all the typing overrides when the dev o
}
```

Then, you will be able to import from `vue-router/auto` (instead of `vue-router`) to get access to the typed APIs.
The generated _Route Map_ is picked up by `unplugin-vue-router/client` types and configures the `vue-router` types to be aware of the routes in your application. Making everything type safe!

::: tip
You can commit the newly added `.d.ts` files to your repository to make your life easier.
Expand All @@ -33,17 +33,13 @@ router.push('')

## Extra types

You can always take a look at the generated `typed-router.d.ts` file to inspect what are the generated types. `unplugin-vue-router` improves upon many of the existing types in `vue-router` and adds a few ones as well:

### `RouteNamedMap`

The `RouteNamedMap` interface gives you access to all the metadata associated with a route. It can also be extended to enable types for **dynamic routes** that are added during runtime.
You can always take a look at the generated `typed-router.d.ts` file to inspect what are the generated types. `unplugin-vue-router` creates a `RouteNamedMap` interface and exports it from `'vue-router/auto-routes'`.

```ts
import type { RouteNamedMap } from 'vue-router/auto-routes'
```

Extending types with dynamically added routes:
This interface contains all the routes in your application along with their metadata. Augment it to add types for **dynamic routes** that are added during runtime:

```ts
export {} // needed in .d.ts files
Expand All @@ -70,27 +66,7 @@ declare module 'vue-router/auto-routes' {
}
```

### `Router`

The `Router` type gives you access to the typed version of the router instance. It's also the _ReturnType_ of the `useRouter()` function.

```ts
import type { Router } from 'vue-router'
```

### `RouteLocationResolved`

The `RouteLocationResolved` type exposed by `vue-router/auto` allows passing a generic (which autocomplete) to type a route **whenever checking the name doesn't makes sense because you know the type**. This is useful for cases like `<RouterLink v-slot="{ route }">`:

```vue
<RouterLink v-slot="{ route }">
User {{ (route as RouteLocationResolved<'/users/[id]'>).params.id }}
</RouterLink>
```

This type is also the return type of `router.resolve()`.

You have the same equivalents for `RouteLocation`, `RouteLocationNormalized`, and `RouteLocationNormalizedLoaded`. All of them exist in `vue-router` but `vue-router/auto` override them to provide a type safe version of them. In addition to that, you can pass the name of the route as a generic:
You can now pass a _type param_ to the generic route location types to narrow down the type of the route:

```ts twoslash
// ---cut-start---
Expand Down
45 changes: 20 additions & 25 deletions docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,19 @@ declare module 'vue-router/auto-routes' {
* Route name map generated by unplugin-vue-router
*/
export interface RouteNamedMap {
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
'/about': RouteRecordInfo<'/about', '/about', Record<never, never>, Record<never, never>>,
'/users/[id]': RouteRecordInfo<'/[id]', '/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>
'/about': RouteRecordInfo<
'/about',
'/about',
Record<never, never>,
Record<never, never>
>
'/users/[id]': RouteRecordInfo<
'/[id]',
'/:id',
{ id: ParamValue<true> },
{ id: ParamValue<false> }
>
}
}
```
Expand Down Expand Up @@ -152,21 +162,22 @@ If you don't have an `env.d.ts` file, you can create one and add the unplugin-vu

:::

Instead of importing from `vue-router`, you should import from `vue-router/auto`.
::: warning

unplugin-vue-router will add a virtual `vue-router/auto` module that exports everything from `vue-router` with some extra features from `unplugin-vue-router/runtime`. It's recommended to avoid using `vue-router/auto` in new projects. It's kept for compatibility with existing projects that use it and will likely be removed in the future.

::: tip
You can exclude `vue-router` from VSCode import suggestions by adding this setting to your `.vscode/settings.json`:
You can exclude `vue-router/auto` from VSCode import suggestions by adding this setting to your `.vscode/settings.json`:

```json
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.preferences.autoImportFileExcludePatterns": ["vue-router$"]
"typescript.preferences.autoImportFileExcludePatterns": ["vue-router/auto$"]
}
```

This will ensure VSCode only suggests `vue-router/auto` for imports. Alternatively, you can also configure [auto imports](#auto-imports).
This will ensure VSCode does not suggest `vue-router/auto` for imports. Alternatively, you can also configure [auto imports](#auto-imports).

The reason we need to import from `vue-router/auto` rather than `vue-router` is because we override all the types with typed version. It is **not possible** to override the types from `vue-router` directly as the typed ones are all generic.
:::

### Migrating an existing project
Expand Down Expand Up @@ -219,7 +230,7 @@ Check the [file-based routing](/guide/file-based-routing) guide for more informa
### From scratch

- Create a `src/pages` folder and add an `index.vue` component to it. This will render your home page at `/`.
- Add Vue Router using `vue-router/auto` instead of `vue-router`. These types are augmented to be fully typed.
- Import the `routes` from `vue-router/auto-routes` and pass them to the `createRouter` function.

::: code-group

Expand Down Expand Up @@ -308,21 +319,5 @@ export default defineConfig({
})
```

FIXME: DELETE

Note that the `vue-router` preset might export less things than the one exported by `unplugin-vue-router` so you might need to add any other imports you were relying on manually:

```ts
AutoImport({
imports: [
VueRouterAutoImports,
{ // [!code ++]
// add any other imports you were relying on // [!code ++]
'vue-router/auto': ['useLink'] // [!code ++]
}, // [!code ++]
],
}),
```

If you use ESlint, check [the ESlint section](/guide/eslint).
If you use TypeScript or have a `jsconfig.json` file, check [the TypeScript section](/guide/typescript).
10 changes: 3 additions & 7 deletions docs/rfcs/data-loaders/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ You might only be interested in trying out Data Loaders. In that case, check out
```ts{2,9}
import { createApp } from 'vue'
import { createRouter } from 'vue-router'
import { DataLoaderPlugin } from 'vue-router/auto'
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders'
const router = createRouter({
// ...
Expand Down Expand Up @@ -564,7 +564,7 @@ Since navigation loaders can run in parallel, they can return different navigati
import 'unplugin-vue-router/client'
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { DataLoaderPlugin } from 'vue-router/auto'
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders'
const app = createApp({})
const router = createRouter({
history: createWebHistory(),
Expand Down Expand Up @@ -598,7 +598,7 @@ By default, `selectNavigation` returns the first value of the array.
If a loader wants to eagerly alter the navigation, it can `throw` the `NavigationResult` instead of returning it. This skips the `selectNavigationResult()` and take precedence without triggering `router.onError()`.

```ts{10-15}
import { NavigationResult } from 'vue-router/auto'
import { NavigationResult } from 'unplugin-vue-router/data-loaders'
export const useUserData = defineLoader(
async (to) => {
Expand Down Expand Up @@ -830,10 +830,6 @@ This aligns with the future [Navigation API](https://github.com/WICG/navigation-

### Implementations

::: info
Ideally, we would import from `vue-router/auto`. This should be added by [unplugin-vue-router][uvr] but given the current state, we need to import from `unplugin-vue-router/data-loaders/...`.
:::

### Interfaces

Defining a minimal set of information and options for Data Loaders is what enables external libraries to implement their own data loaders. They are meant to extend these interfaces to add more features that are specific to them. You can see a practical example with the [Pinia Colada](colada.md) implementation.
Expand Down
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@
"require": "./dist/types.cjs",
"import": "./dist/types.js"
},
"./data-loaders": {
"types": {
"require": "./dist/data-loaders/index.d.cts",
"import": "./dist/data-loaders/index.d.ts"
},
"require": "./dist/data-loaders/index.cjs",
"import": "./dist/data-loaders/index.js"
},
"./data-loaders/basic": {
"types": {
"require": "./dist/data-loaders/basic.d.cts",
Expand Down
8 changes: 4 additions & 4 deletions playground/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
export {}
declare global {
const defineBasicLoader: typeof import('unplugin-vue-router/data-loaders/basic')['defineBasicLoader']
const onBeforeRouteLeave: typeof import('vue-router/auto')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router/auto')['onBeforeRouteUpdate']
const useRoute: typeof import('vue-router/auto')['useRoute']
const useRouter: typeof import('vue-router/auto')['useRouter']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
}
2 changes: 1 addition & 1 deletion playground/src/components/TestSetup.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { onBeforeRouteLeave } from 'vue-router/auto'
import { onBeforeRouteLeave } from 'vue-router'
onBeforeRouteLeave((to) => {
if (to.name === '/[name]') {
Expand Down
2 changes: 1 addition & 1 deletion playground/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createApp } from 'vue'
import App from './App.vue'
// FIXME:
import { DataLoaderPlugin } from 'vue-router/auto'
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders'
// import { DataLoaderPlugin } from 'unplugin-vue-router/runtime'
import { MutationCache, QueryCache, VueQueryPlugin } from '@tanstack/vue-query'
import { createPinia } from 'pinia'
Expand Down
2 changes: 1 addition & 1 deletion playground/src/pages/[...path]+.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useRoute } from 'vue-router/auto'
import { useRoute } from 'vue-router'
const route = useRoute('/[...path]+')
</script>
Expand Down
2 changes: 1 addition & 1 deletion playground/src/pages/users/query.[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { type RouteRecordName } from 'vue-router'
import { computed } from 'vue'
const a: RouteRecordName = '/articles'
// import type { RouteLocationNormalized, _RouteLocationNormalized } from 'vue-router/auto'
// import type { RouteLocationNormalized, _RouteLocationNormalized } from 'vue-router'
import type {
RouteLocationNormalized,
RouteLocationNormalized as _RouteLocationNormalized,
Expand Down
7 changes: 2 additions & 5 deletions playground/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { inject, toValue, onUnmounted } from 'vue'
import type {
RouteLocation,
RouteLocationNormalizedLoaded,
} from 'vue-router/auto'
import { viewDepthKey, useRoute, useRouter } from 'vue-router/auto'
import type { RouteLocation, RouteLocationNormalizedLoaded } from 'vue-router'
import { viewDepthKey, useRoute, useRouter } from 'vue-router'
import type { RouteNamedMap } from 'vue-router/auto-routes'

type NavigationReturn = RouteLocation | boolean | void
Expand Down
3 changes: 3 additions & 0 deletions playground/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"unplugin-vue-router/types": [
"../src/types"
],
"unplugin-vue-router/data-loaders": [
"../src/data-loaders/index"
],
"unplugin-vue-router/data-loaders/basic": [
"../src/data-loaders/basic"
],
Expand Down
5 changes: 2 additions & 3 deletions src/codegen/vueRouterModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ export function generateVueRouterProxy(
import { createRouter as _createRouter } from 'vue-router'
export * from 'vue-router'
export { definePage } from 'unplugin-vue-router/runtime'
export {
definePage,
// new data fetching
DataLoaderPlugin,
NavigationResult,
} from 'unplugin-vue-router/runtime'
} from 'unplugin-vue-router/data-loaders'
export * from 'unplugin-vue-router/data-loaders/basic'
${addPiniaColada ? "export * from 'unplugin-vue-router/data-loaders/pinia-colada'" : ''}
Expand Down
10 changes: 10 additions & 0 deletions src/data-loaders/entries/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export {
DataLoaderPlugin,
NavigationResult,
withLoaderContext,
} from 'unplugin-vue-router/runtime'
export type {
DataLoaderPluginOptions,
SetupLoaderGuardOptions,
_DataLoaderRedirectResult,
} from 'unplugin-vue-router/runtime'
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export const VueRouterAutoImports: Record<
string,
Array<string | [importName: string, alias: string]>
> = {
'vue-router/auto': [
'vue-router': [
'useRoute',
'useRouter',
'onBeforeRouteUpdate',
Expand Down
1 change: 1 addition & 0 deletions tests/data-loaders/tester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
type DataLoaderContextBase,
type DefineDataLoaderOptionsBase,
type UseDataLoader,
// TODO: move to /data-loaders
} from 'unplugin-vue-router/runtime'
import { mockPromise } from '../utils'
import RouterViewMock from '../data-loaders/RouterViewMock.vue'
Expand Down

0 comments on commit 5f8a5a7

Please sign in to comment.