@virou/core 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index.d.ts +106 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +178 -0
- package/dist/index.js.map +1 -0
- package/package.json +7 -8
- package/dist/index.d.mts +0 -107
- package/dist/index.mjs +0 -182
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<p>
|
|
4
4
|
<a href="https://www.npmjs.com/package/@virou/core"><img src="https://img.shields.io/npm/v/@virou/core.svg?style=flat&colorA=18181B&colorB=39737d" alt="Version"></a>
|
|
5
5
|
<a href="https://www.npmjs.com/package/@virou/core"><img src="https://img.shields.io/npm/dm/@virou/core.svg?style=flat&colorA=18181B&colorB=39737d" alt="Downloads"></a>
|
|
6
|
-
<a href="https://bundlephobia.com/package/@virou/core"><img src="https://img.shields.io/bundlephobia/min/@virou/core?style=flat&colorA=18181B&colorB=39737d" alt="Bundle Size"
|
|
6
|
+
<a href="https://bundlephobia.com/package/@virou/core"><img src="https://img.shields.io/bundlephobia/min/@virou/core?style=flat&colorA=18181B&colorB=39737d" alt="Bundle Size"><a/>
|
|
7
7
|
<a href="https://github.com/tankosinn/virou/tree/main/LICENSE"><img src="https://img.shields.io/github/license/tankosinn/virou.svg?style=flat&colorA=18181B&colorB=39737d" alt="License"></a>
|
|
8
8
|
</p>
|
|
9
9
|
|
|
@@ -66,6 +66,8 @@ createApp(App)
|
|
|
66
66
|
.mount('#app')
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
> ⚠️ Virou doesn’t globally register any components (including `VRouterView`); it only adds a `$virou` global property to store router instances in a `Map<string, VRouterData>`, which are automatically removed when no longer in use.
|
|
70
|
+
|
|
69
71
|
### 🧩 Using with Nuxt
|
|
70
72
|
|
|
71
73
|
Install Virou Nuxt module with your package manager:
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { RouterContext } from "rou3";
|
|
2
|
+
import * as vue0 from "vue";
|
|
3
|
+
import { Component, DefineComponent, Plugin, PropType, Ref, ShallowRef, SlotsType, VNodeChild } from "vue";
|
|
4
|
+
|
|
5
|
+
//#region src/types.d.ts
|
|
6
|
+
type Lazy<T> = () => Promise<T>;
|
|
7
|
+
type VRouteComponent = Component | DefineComponent;
|
|
8
|
+
type VRouteLazyComponent = Lazy<VRouteComponent>;
|
|
9
|
+
type VRouteRenderComponent = VRouteComponent | VRouteLazyComponent;
|
|
10
|
+
type VRouteMeta = Record<PropertyKey, unknown>;
|
|
11
|
+
interface VRouteRaw {
|
|
12
|
+
path: string;
|
|
13
|
+
component: VRouteRenderComponent;
|
|
14
|
+
meta?: VRouteMeta;
|
|
15
|
+
children?: VRouteRaw[];
|
|
16
|
+
}
|
|
17
|
+
type VRouteId = Readonly<[path: string, depth: number]>;
|
|
18
|
+
interface VRouteMatchedData {
|
|
19
|
+
id: VRouteId;
|
|
20
|
+
meta?: VRouteMeta;
|
|
21
|
+
}
|
|
22
|
+
interface VRouteNormalized extends Omit<VRouteRaw, 'path' | 'children'> {
|
|
23
|
+
parentId?: VRouteId;
|
|
24
|
+
}
|
|
25
|
+
type VRoutesMap = Map<VRouteId, VRouteNormalized>;
|
|
26
|
+
interface VRoute {
|
|
27
|
+
fullPath: string;
|
|
28
|
+
meta?: VRouteMeta;
|
|
29
|
+
params?: Record<string, string>;
|
|
30
|
+
path: string;
|
|
31
|
+
search: string;
|
|
32
|
+
hash: string;
|
|
33
|
+
_renderList: Component[] | null;
|
|
34
|
+
}
|
|
35
|
+
interface VRouterData {
|
|
36
|
+
context: RouterContext<VRouteMatchedData>;
|
|
37
|
+
routes: VRoutesMap;
|
|
38
|
+
activePath: Ref<string>;
|
|
39
|
+
route: ShallowRef<VRoute>;
|
|
40
|
+
_isGlobal: boolean;
|
|
41
|
+
_deps: number;
|
|
42
|
+
_dispose: () => void;
|
|
43
|
+
}
|
|
44
|
+
interface VRouterOptions {
|
|
45
|
+
initialPath?: string;
|
|
46
|
+
_isGlobal?: boolean;
|
|
47
|
+
}
|
|
48
|
+
interface VRouter {
|
|
49
|
+
route: VRouterData['route'];
|
|
50
|
+
router: {
|
|
51
|
+
addRoute: (route: VRouteRaw) => void;
|
|
52
|
+
replace: (path: string) => void;
|
|
53
|
+
_depthKey: symbol;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
interface VirouPluginOptions {
|
|
57
|
+
routers?: Record<string, {
|
|
58
|
+
routes: VRouteRaw[];
|
|
59
|
+
options?: Omit<VRouterOptions, '_isGlobal'>;
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/component.d.ts
|
|
64
|
+
declare const VRouterView: vue0.DefineComponent<vue0.ExtractPropTypes<{
|
|
65
|
+
routerKey: StringConstructor;
|
|
66
|
+
keepAlive: {
|
|
67
|
+
type: BooleanConstructor;
|
|
68
|
+
default: boolean;
|
|
69
|
+
};
|
|
70
|
+
viewKey: {
|
|
71
|
+
type: PropType<string | ((route: VRoute, key: string) => string)>;
|
|
72
|
+
};
|
|
73
|
+
}>, () => string | number | boolean | vue0.VNode<vue0.RendererNode, vue0.RendererElement, {
|
|
74
|
+
[key: string]: any;
|
|
75
|
+
}> | vue0.VNodeArrayChildren | null, {}, {}, {}, vue0.ComponentOptionsMixin, vue0.ComponentOptionsMixin, {}, string, vue0.PublicProps, Readonly<vue0.ExtractPropTypes<{
|
|
76
|
+
routerKey: StringConstructor;
|
|
77
|
+
keepAlive: {
|
|
78
|
+
type: BooleanConstructor;
|
|
79
|
+
default: boolean;
|
|
80
|
+
};
|
|
81
|
+
viewKey: {
|
|
82
|
+
type: PropType<string | ((route: VRoute, key: string) => string)>;
|
|
83
|
+
};
|
|
84
|
+
}>> & Readonly<{}>, {
|
|
85
|
+
keepAlive: boolean;
|
|
86
|
+
}, SlotsType<{
|
|
87
|
+
default: (payload: {
|
|
88
|
+
Component: VNodeChild;
|
|
89
|
+
route: VRoute;
|
|
90
|
+
}) => VNodeChild;
|
|
91
|
+
fallback: (payload: {
|
|
92
|
+
route: VRoute;
|
|
93
|
+
}) => VNodeChild;
|
|
94
|
+
}>, {}, {}, string, vue0.ComponentProvideOptions, true, {}, any>;
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/plugin.d.ts
|
|
97
|
+
declare const virou: Plugin<[VirouPluginOptions?]>;
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/router.d.ts
|
|
100
|
+
declare const virouSymbol: unique symbol;
|
|
101
|
+
declare function createVRouter(routes: VRouteRaw[], options?: VRouterOptions): VRouterData;
|
|
102
|
+
declare function useVRouter(routes?: VRouteRaw[], options?: VRouterOptions): VRouter;
|
|
103
|
+
declare function useVRouter(key?: string, routes?: VRouteRaw[], options?: VRouterOptions): VRouter;
|
|
104
|
+
//#endregion
|
|
105
|
+
export { VRoute, VRouteComponent, VRouteId, VRouteLazyComponent, VRouteMatchedData, VRouteMeta, VRouteNormalized, VRouteRaw, VRouteRenderComponent, VRouter, VRouterData, VRouterOptions, VRouterView, VRoutesMap, VirouPluginOptions, createVRouter, useVRouter, virou, virouSymbol };
|
|
106
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/component.ts","../src/plugin.ts","../src/router.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { addRoute, createRouter, findRoute } from "rou3";
|
|
2
|
+
import { KeepAlive, Suspense, defineAsyncComponent, defineComponent, getCurrentInstance, h, inject, onScopeDispose, provide, ref, shallowRef, useId, watchEffect } from "vue";
|
|
3
|
+
import { joinURL, parseURL } from "ufo";
|
|
4
|
+
|
|
5
|
+
//#region src/utils.ts
|
|
6
|
+
const renderListCache = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
function normalizeComponent(component) {
|
|
8
|
+
if (typeof component === "function" && component.length === 0) return defineAsyncComponent(component);
|
|
9
|
+
return component;
|
|
10
|
+
}
|
|
11
|
+
function registerRoutes(ctx, routes, registry, parentId) {
|
|
12
|
+
for (const { path, meta, component, children } of routes) {
|
|
13
|
+
const fullPath = joinURL(parentId?.[0] ?? "/", path);
|
|
14
|
+
const depth = (parentId?.[1] ?? -1) + 1;
|
|
15
|
+
const id = Object.freeze([fullPath, depth]);
|
|
16
|
+
registry.set(id, {
|
|
17
|
+
meta,
|
|
18
|
+
component: normalizeComponent(component),
|
|
19
|
+
parentId
|
|
20
|
+
});
|
|
21
|
+
if (children && children.length) registerRoutes(ctx, children, registry, id);
|
|
22
|
+
addRoute(ctx, "GET", fullPath, {
|
|
23
|
+
id,
|
|
24
|
+
meta
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function createRenderList(data, routes) {
|
|
29
|
+
let cacheForRoutes = renderListCache.get(routes);
|
|
30
|
+
if (!cacheForRoutes) {
|
|
31
|
+
cacheForRoutes = /* @__PURE__ */ new Map();
|
|
32
|
+
renderListCache.set(routes, cacheForRoutes);
|
|
33
|
+
}
|
|
34
|
+
const cached = cacheForRoutes.get(data.id);
|
|
35
|
+
if (cached) return cached;
|
|
36
|
+
const depth = data.id[1];
|
|
37
|
+
const list = Array.from({ length: depth });
|
|
38
|
+
let idx = depth;
|
|
39
|
+
let cursor = routes.get(data.id);
|
|
40
|
+
while (cursor) {
|
|
41
|
+
list[idx--] = cursor.component;
|
|
42
|
+
cursor = cursor.parentId !== void 0 ? routes.get(cursor.parentId) : void 0;
|
|
43
|
+
}
|
|
44
|
+
cacheForRoutes.set(data.id, list);
|
|
45
|
+
return list;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/router.ts
|
|
50
|
+
const virouSymbol = Symbol("virou");
|
|
51
|
+
function createVRouter(routes, options) {
|
|
52
|
+
const context = createRouter();
|
|
53
|
+
const routeRegistry = /* @__PURE__ */ new Map();
|
|
54
|
+
registerRoutes(context, routes, routeRegistry);
|
|
55
|
+
const activePath = ref(options?.initialPath ?? "/");
|
|
56
|
+
const snapshot = () => {
|
|
57
|
+
const matchedRoute = findRoute(context, "GET", activePath.value);
|
|
58
|
+
const _renderList = matchedRoute ? createRenderList(matchedRoute.data, routeRegistry) : null;
|
|
59
|
+
const { pathname, hash, search } = parseURL(activePath.value);
|
|
60
|
+
return {
|
|
61
|
+
fullPath: activePath.value,
|
|
62
|
+
path: pathname,
|
|
63
|
+
search,
|
|
64
|
+
hash,
|
|
65
|
+
meta: matchedRoute?.data.meta,
|
|
66
|
+
params: matchedRoute?.params,
|
|
67
|
+
_renderList
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const route = shallowRef(snapshot());
|
|
71
|
+
const unwatch = watchEffect(() => {
|
|
72
|
+
route.value = snapshot();
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
context,
|
|
76
|
+
routes: routeRegistry,
|
|
77
|
+
activePath,
|
|
78
|
+
route,
|
|
79
|
+
_isGlobal: options?._isGlobal ?? false,
|
|
80
|
+
_deps: 0,
|
|
81
|
+
_dispose: unwatch
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function useVRouter(...args) {
|
|
85
|
+
if (typeof args[0] !== "string") args.unshift(inject(virouSymbol, useId()));
|
|
86
|
+
const [key, routes = [], options = {}] = args;
|
|
87
|
+
if (!key || typeof key !== "string") throw new TypeError(`[virou] [useVRouter] key must be a string: ${key}`);
|
|
88
|
+
provide(virouSymbol, key);
|
|
89
|
+
const vm = getCurrentInstance();
|
|
90
|
+
if (!vm) throw new TypeError("[virou] [useVRouter] useVRouter must be called in setup()");
|
|
91
|
+
const virou$1 = vm.proxy?.$virou;
|
|
92
|
+
if (!virou$1) throw new Error("[virou] [useVRouter] virou plugin not installed");
|
|
93
|
+
if (routes.length) {
|
|
94
|
+
if (virou$1.get(key)) throw new Error(`[virou] [useVRouter] router with key "${key}" already exists`);
|
|
95
|
+
virou$1.set(key, createVRouter(routes, options));
|
|
96
|
+
}
|
|
97
|
+
const router = virou$1.get(key);
|
|
98
|
+
if (!router) throw new Error(`[virou] [useVRouter] router with key "${key}" not found`);
|
|
99
|
+
router._deps++;
|
|
100
|
+
onScopeDispose(() => {
|
|
101
|
+
router._deps--;
|
|
102
|
+
if (router._deps === 0 && !router._isGlobal) {
|
|
103
|
+
router._dispose();
|
|
104
|
+
virou$1.delete(key);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
route: router.route,
|
|
109
|
+
router: {
|
|
110
|
+
addRoute: (route) => {
|
|
111
|
+
registerRoutes(router.context, [route], router.routes);
|
|
112
|
+
},
|
|
113
|
+
replace: (path) => {
|
|
114
|
+
router.activePath.value = path;
|
|
115
|
+
},
|
|
116
|
+
_depthKey: Symbol.for(key)
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/component.ts
|
|
123
|
+
const VRouterView = defineComponent({
|
|
124
|
+
name: "VRouterView",
|
|
125
|
+
inheritAttrs: false,
|
|
126
|
+
props: {
|
|
127
|
+
routerKey: String,
|
|
128
|
+
keepAlive: {
|
|
129
|
+
type: Boolean,
|
|
130
|
+
default: false
|
|
131
|
+
},
|
|
132
|
+
viewKey: { type: [String, Function] }
|
|
133
|
+
},
|
|
134
|
+
slots: Object,
|
|
135
|
+
setup(props, { slots, attrs }) {
|
|
136
|
+
const key = props.routerKey ?? inject(virouSymbol);
|
|
137
|
+
if (key === void 0) throw new Error("[virou] [VRouterView] routerKey is required");
|
|
138
|
+
const { route, router } = useVRouter(key);
|
|
139
|
+
const depth = inject(router._depthKey, 0);
|
|
140
|
+
provide(router._depthKey, depth + 1);
|
|
141
|
+
return () => {
|
|
142
|
+
const component = route.value._renderList?.[depth];
|
|
143
|
+
if (!component) return slots.default?.({
|
|
144
|
+
Component: null,
|
|
145
|
+
route: route.value
|
|
146
|
+
}) ?? null;
|
|
147
|
+
const vnodeKey = typeof props.viewKey === "function" ? props.viewKey(route.value, key) : props.viewKey ?? `${key}-${depth}-${route.value.path}`;
|
|
148
|
+
const suspenseVNode = h(Suspense, null, {
|
|
149
|
+
default: () => h(component, {
|
|
150
|
+
key: vnodeKey,
|
|
151
|
+
...attrs
|
|
152
|
+
}),
|
|
153
|
+
fallback: () => slots.fallback?.({ route: route.value }) ?? null
|
|
154
|
+
});
|
|
155
|
+
const vnode = props.keepAlive ? h(KeepAlive, null, { default: () => suspenseVNode }) : suspenseVNode;
|
|
156
|
+
return slots.default?.({
|
|
157
|
+
Component: vnode,
|
|
158
|
+
route: route.value
|
|
159
|
+
}) ?? vnode;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/plugin.ts
|
|
166
|
+
const virou = (app, options = {}) => {
|
|
167
|
+
const { routers } = options;
|
|
168
|
+
const map = /* @__PURE__ */ new Map();
|
|
169
|
+
app.config.globalProperties.$virou = map;
|
|
170
|
+
if (routers) for (const [key, router] of Object.entries(routers)) map.set(key, createVRouter(router.routes, {
|
|
171
|
+
...router.options,
|
|
172
|
+
_isGlobal: true
|
|
173
|
+
}));
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
export { VRouterView, createVRouter, useVRouter, virou, virouSymbol };
|
|
178
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["id: VRouteId","routeRegistry: VRoutesMap","virou","virou: Plugin<[VirouPluginOptions?]>"],"sources":["../src/utils.ts","../src/router.ts","../src/component.ts","../src/plugin.ts"],"sourcesContent":["import type { RouterContext } from 'rou3'\nimport type { Component } from 'vue'\nimport type { VRouteId, VRouteLazyComponent, VRouteMatchedData, VRouteRaw, VRouteRenderComponent, VRoutesMap } from './types'\nimport { addRoute } from 'rou3'\nimport { joinURL } from 'ufo'\nimport { defineAsyncComponent } from 'vue'\n\nconst renderListCache = new WeakMap<VRoutesMap, Map<VRouteId, Component[]>>()\n\nfunction normalizeComponent(component: VRouteRenderComponent): Component {\n if (typeof component === 'function' && (component as VRouteLazyComponent).length === 0) {\n return defineAsyncComponent(component as VRouteLazyComponent)\n }\n return component as Component\n}\n\nexport function registerRoutes(\n ctx: RouterContext<VRouteMatchedData>,\n routes: VRouteRaw[],\n registry: VRoutesMap,\n parentId?: VRouteId,\n): void {\n for (const { path, meta, component, children } of routes) {\n const fullPath = joinURL(parentId?.[0] ?? '/', path)\n const depth = (parentId?.[1] ?? -1) + 1\n\n const id: VRouteId = Object.freeze([fullPath, depth])\n\n registry.set(id, {\n meta,\n component: normalizeComponent(component),\n parentId,\n })\n\n if (children && children.length) {\n registerRoutes(ctx, children, registry, id)\n }\n\n addRoute(ctx, 'GET', fullPath, { id, meta })\n }\n}\n\nexport function createRenderList(\n data: VRouteMatchedData,\n routes: VRoutesMap,\n): VRouteRenderComponent[] {\n let cacheForRoutes = renderListCache.get(routes)\n if (!cacheForRoutes) {\n cacheForRoutes = new Map<VRouteId, Component[]>()\n renderListCache.set(routes, cacheForRoutes)\n }\n\n const cached = cacheForRoutes.get(data.id)\n if (cached) {\n return cached\n }\n\n const depth = data.id[1]\n const list = Array.from<VRouteRenderComponent>({ length: depth })\n let idx = depth\n let cursor = routes.get(data.id)\n while (cursor) {\n list[idx--] = cursor.component\n cursor = cursor.parentId !== undefined ? routes.get(cursor.parentId) : undefined\n }\n\n cacheForRoutes.set(data.id, list)\n return list\n}\n","import type { VRoute, VRouteMatchedData, VRouter, VRouteRaw, VRouterData, VRouterOptions, VRoutesMap } from './types'\nimport { createRouter, findRoute } from 'rou3'\nimport { parseURL } from 'ufo'\nimport { getCurrentInstance, inject, onScopeDispose, provide, ref, shallowRef, useId, watchEffect } from 'vue'\nimport { createRenderList, registerRoutes } from './utils'\n\nexport const virouSymbol = Symbol('virou')\n\nexport function createVRouter(routes: VRouteRaw[], options?: VRouterOptions): VRouterData {\n const context = createRouter<VRouteMatchedData>()\n const routeRegistry: VRoutesMap = new Map()\n registerRoutes(context, routes, routeRegistry)\n\n const activePath = ref(options?.initialPath ?? '/')\n\n const snapshot = (): VRoute => {\n const matchedRoute = findRoute(context, 'GET', activePath.value)\n const _renderList = matchedRoute ? createRenderList(matchedRoute.data, routeRegistry) : null\n const { pathname, hash, search } = parseURL(activePath.value)\n return {\n fullPath: activePath.value,\n path: pathname,\n search,\n hash,\n meta: matchedRoute?.data.meta,\n params: matchedRoute?.params,\n _renderList,\n }\n }\n\n const route = shallowRef<VRoute>(snapshot())\n\n const unwatch = watchEffect(() => {\n route.value = snapshot()\n })\n\n return {\n context,\n routes: routeRegistry,\n activePath,\n route,\n _isGlobal: options?._isGlobal ?? false,\n _deps: 0,\n _dispose: unwatch,\n }\n}\n\nexport function useVRouter(routes?: VRouteRaw[], options?: VRouterOptions): VRouter\nexport function useVRouter(key?: string, routes?: VRouteRaw[], options?: VRouterOptions): VRouter\nexport function useVRouter(...args: any[]): VRouter {\n if (typeof args[0] !== 'string') {\n args.unshift(inject<string>(virouSymbol, useId()))\n }\n\n const [key, routes = [], options = {}] = args as [string, VRouteRaw[], VRouterOptions]\n\n if (!key || typeof key !== 'string') {\n throw new TypeError(`[virou] [useVRouter] key must be a string: ${key}`)\n }\n\n provide(virouSymbol, key)\n\n const vm = getCurrentInstance()\n if (!vm) {\n throw new TypeError('[virou] [useVRouter] useVRouter must be called in setup()')\n }\n\n const virou = vm.proxy?.$virou\n if (!virou) {\n throw new Error('[virou] [useVRouter] virou plugin not installed')\n }\n\n if (routes.length) {\n if (virou.get(key)) {\n throw new Error(`[virou] [useVRouter] router with key \"${key}\" already exists`)\n }\n\n virou.set(key, createVRouter(routes, options))\n }\n\n const router = virou.get(key)\n if (!router) {\n throw new Error(`[virou] [useVRouter] router with key \"${key}\" not found`)\n }\n\n router._deps++\n onScopeDispose(() => {\n router._deps--\n\n if (router._deps === 0 && !router._isGlobal) {\n router._dispose()\n virou.delete(key)\n }\n })\n\n return {\n route: router.route,\n router: {\n addRoute: (route: VRouteRaw) => {\n registerRoutes(router.context, [route], router.routes)\n },\n replace: (path: string) => {\n router.activePath.value = path\n },\n _depthKey: Symbol.for(key),\n },\n }\n}\n","import type { PropType, SlotsType, VNodeChild } from 'vue'\nimport type { VRoute } from './types'\nimport {\n defineComponent,\n h,\n inject,\n KeepAlive,\n provide,\n Suspense,\n} from 'vue'\nimport { useVRouter, virouSymbol } from './router'\n\nexport const VRouterView = defineComponent({\n name: 'VRouterView',\n inheritAttrs: false,\n props: {\n routerKey: String,\n keepAlive: { type: Boolean, default: false },\n viewKey: { type: [String, Function] as PropType<string | ((route: VRoute, key: string) => string)> },\n },\n slots: Object as SlotsType<{\n default: (payload: { Component: VNodeChild, route: VRoute }) => VNodeChild\n fallback: (payload: { route: VRoute }) => VNodeChild\n }>,\n setup(props, { slots, attrs }) {\n const key = props.routerKey ?? inject<string>(virouSymbol)\n if (key === undefined) {\n throw new Error('[virou] [VRouterView] routerKey is required')\n }\n\n const { route, router } = useVRouter(key)\n\n const depth = inject<number>(router._depthKey, 0)\n provide(router._depthKey, depth + 1)\n\n return () => {\n const component = route.value._renderList?.[depth]\n if (!component) {\n return slots.default?.({ Component: null, route: route.value }) ?? null\n }\n\n const vnodeKey = typeof props.viewKey === 'function'\n ? props.viewKey(route.value, key)\n : props.viewKey ?? `${key}-${depth}-${route.value.path}`\n\n const suspenseVNode = h(\n Suspense,\n null,\n {\n default: () => h(component, { key: vnodeKey, ...attrs }),\n fallback: () => slots.fallback?.({ route: route.value }) ?? null,\n },\n )\n\n const vnode = props.keepAlive\n ? h(KeepAlive, null, { default: () => suspenseVNode })\n : suspenseVNode\n\n return slots.default?.({ Component: vnode, route: route.value }) ?? vnode\n }\n },\n})\n","import type { Plugin } from 'vue'\nimport type { VirouPluginOptions, VRouterData } from './types'\nimport { createVRouter } from './router'\n\nexport const virou: Plugin<[VirouPluginOptions?]> = (app, options = {}) => {\n const { routers } = options\n\n const map = new Map<string, VRouterData>()\n app.config.globalProperties.$virou = map\n\n if (routers) {\n for (const [key, router] of Object.entries(routers)) {\n map.set(key, createVRouter(router.routes, { ...router.options, _isGlobal: true }))\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@virou/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"description": "Virtual router with multiple instance support for Vue",
|
|
6
6
|
"author": "Tankosin<https://github.com/tankosinn>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -22,9 +22,11 @@
|
|
|
22
22
|
],
|
|
23
23
|
"sideEffects": false,
|
|
24
24
|
"exports": {
|
|
25
|
-
"types": "./dist/index.d.
|
|
26
|
-
"default": "./dist/index.
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
27
|
},
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
28
30
|
"files": [
|
|
29
31
|
"dist"
|
|
30
32
|
],
|
|
@@ -32,13 +34,10 @@
|
|
|
32
34
|
"vue": "^3.5.0"
|
|
33
35
|
},
|
|
34
36
|
"dependencies": {
|
|
35
|
-
"rou3": "^0.
|
|
37
|
+
"rou3": "^0.7.11",
|
|
36
38
|
"ufo": "^1.6.1"
|
|
37
39
|
},
|
|
38
|
-
"devDependencies": {
|
|
39
|
-
"unbuild": "3.5.0"
|
|
40
|
-
},
|
|
41
40
|
"scripts": {
|
|
42
|
-
"build": "
|
|
41
|
+
"build": "pnpm -w tsdown -F @virou/core"
|
|
43
42
|
}
|
|
44
43
|
}
|
package/dist/index.d.mts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { RouterContext } from 'rou3';
|
|
2
|
-
import * as vue from 'vue';
|
|
3
|
-
import { Component, DefineComponent, Ref, ShallowRef, PropType, SlotsType, VNodeChild, Plugin } from 'vue';
|
|
4
|
-
|
|
5
|
-
type Lazy<T> = () => Promise<T>;
|
|
6
|
-
type VRouteComponent = Component | DefineComponent;
|
|
7
|
-
type VRouteLazyComponent = Lazy<VRouteComponent>;
|
|
8
|
-
type VRouteRenderComponent = VRouteComponent | VRouteLazyComponent;
|
|
9
|
-
type VRouteMeta = Record<PropertyKey, unknown>;
|
|
10
|
-
interface VRouteRaw {
|
|
11
|
-
path: string;
|
|
12
|
-
component: VRouteRenderComponent;
|
|
13
|
-
meta?: VRouteMeta;
|
|
14
|
-
children?: VRouteRaw[];
|
|
15
|
-
}
|
|
16
|
-
type VRouteId = Readonly<[path: string, depth: number]>;
|
|
17
|
-
interface VRouteMatchedData {
|
|
18
|
-
id: VRouteId;
|
|
19
|
-
meta?: VRouteMeta;
|
|
20
|
-
}
|
|
21
|
-
interface VRouteNormalized extends Omit<VRouteRaw, 'path' | 'children'> {
|
|
22
|
-
parentId?: VRouteId;
|
|
23
|
-
}
|
|
24
|
-
type VRoutesMap = Map<VRouteId, VRouteNormalized>;
|
|
25
|
-
interface VRoute {
|
|
26
|
-
fullPath: string;
|
|
27
|
-
meta?: VRouteMeta;
|
|
28
|
-
params?: Record<string, string>;
|
|
29
|
-
path: string;
|
|
30
|
-
search: string;
|
|
31
|
-
hash: string;
|
|
32
|
-
_renderList: Component[] | null;
|
|
33
|
-
}
|
|
34
|
-
interface VRouterData {
|
|
35
|
-
context: RouterContext<VRouteMatchedData>;
|
|
36
|
-
routes: VRoutesMap;
|
|
37
|
-
activePath: Ref<string>;
|
|
38
|
-
route: ShallowRef<VRoute>;
|
|
39
|
-
_isGlobal: boolean;
|
|
40
|
-
_deps: number;
|
|
41
|
-
_dispose: () => void;
|
|
42
|
-
}
|
|
43
|
-
interface VRouterOptions {
|
|
44
|
-
initialPath?: string;
|
|
45
|
-
_isGlobal?: boolean;
|
|
46
|
-
}
|
|
47
|
-
interface VRouter {
|
|
48
|
-
route: VRouterData['route'];
|
|
49
|
-
router: {
|
|
50
|
-
addRoute: (route: VRouteRaw) => void;
|
|
51
|
-
replace: (path: string) => void;
|
|
52
|
-
_depthKey: symbol;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
interface VirouPluginOptions {
|
|
56
|
-
routers?: Record<string, {
|
|
57
|
-
routes: VRouteRaw[];
|
|
58
|
-
options?: Omit<VRouterOptions, '_isGlobal'>;
|
|
59
|
-
}>;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
declare module 'vue' {
|
|
63
|
-
interface ComponentCustomProperties {
|
|
64
|
-
$virou: Map<string, VRouterData>
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
declare const VRouterView: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
69
|
-
routerKey: StringConstructor;
|
|
70
|
-
keepAlive: {
|
|
71
|
-
type: BooleanConstructor;
|
|
72
|
-
default: boolean;
|
|
73
|
-
};
|
|
74
|
-
viewKey: {
|
|
75
|
-
type: PropType<string | ((route: VRoute, key: string) => string)>;
|
|
76
|
-
};
|
|
77
|
-
}>, () => string | number | boolean | vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
78
|
-
[key: string]: any;
|
|
79
|
-
}> | vue.VNodeArrayChildren | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
80
|
-
routerKey: StringConstructor;
|
|
81
|
-
keepAlive: {
|
|
82
|
-
type: BooleanConstructor;
|
|
83
|
-
default: boolean;
|
|
84
|
-
};
|
|
85
|
-
viewKey: {
|
|
86
|
-
type: PropType<string | ((route: VRoute, key: string) => string)>;
|
|
87
|
-
};
|
|
88
|
-
}>> & Readonly<{}>, {
|
|
89
|
-
keepAlive: boolean;
|
|
90
|
-
}, SlotsType<{
|
|
91
|
-
default: (payload: {
|
|
92
|
-
Component: VNodeChild;
|
|
93
|
-
route: VRoute;
|
|
94
|
-
}) => VNodeChild;
|
|
95
|
-
fallback: (payload: {
|
|
96
|
-
route: VRoute;
|
|
97
|
-
}) => VNodeChild;
|
|
98
|
-
}>, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
99
|
-
|
|
100
|
-
declare const virou: Plugin<[VirouPluginOptions?]>;
|
|
101
|
-
|
|
102
|
-
declare const virouSymbol: unique symbol;
|
|
103
|
-
declare function createVRouter(routes: VRouteRaw[], options?: VRouterOptions): VRouterData;
|
|
104
|
-
declare function useVRouter(routes?: VRouteRaw[], options?: VRouterOptions): VRouter;
|
|
105
|
-
declare function useVRouter(key?: string, routes?: VRouteRaw[], options?: VRouterOptions): VRouter;
|
|
106
|
-
|
|
107
|
-
export { type VRoute, type VRouteComponent, type VRouteId, type VRouteLazyComponent, type VRouteMatchedData, type VRouteMeta, type VRouteNormalized, type VRouteRaw, type VRouteRenderComponent, type VRouter, type VRouterData, type VRouterOptions, VRouterView, type VRoutesMap, type VirouPluginOptions, createVRouter, useVRouter, virou, virouSymbol };
|
package/dist/index.mjs
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import { defineAsyncComponent, ref, shallowRef, watchEffect, inject, useId, provide, getCurrentInstance, onScopeDispose, defineComponent, h, Suspense, KeepAlive } from 'vue';
|
|
2
|
-
import { addRoute, createRouter, findRoute } from 'rou3';
|
|
3
|
-
import { joinURL, parseURL } from 'ufo';
|
|
4
|
-
|
|
5
|
-
const renderListCache = /* @__PURE__ */ new WeakMap();
|
|
6
|
-
function normalizeComponent(component) {
|
|
7
|
-
if (typeof component === "function" && component.length === 0) {
|
|
8
|
-
return defineAsyncComponent(component);
|
|
9
|
-
}
|
|
10
|
-
return component;
|
|
11
|
-
}
|
|
12
|
-
function registerRoutes(ctx, routes, registry, parentId) {
|
|
13
|
-
for (const { path, meta, component, children } of routes) {
|
|
14
|
-
const fullPath = joinURL(parentId?.[0] ?? "/", path);
|
|
15
|
-
const depth = (parentId?.[1] ?? -1) + 1;
|
|
16
|
-
const id = Object.freeze([fullPath, depth]);
|
|
17
|
-
registry.set(id, {
|
|
18
|
-
meta,
|
|
19
|
-
component: normalizeComponent(component),
|
|
20
|
-
parentId
|
|
21
|
-
});
|
|
22
|
-
if (children && children.length) {
|
|
23
|
-
registerRoutes(ctx, children, registry, id);
|
|
24
|
-
}
|
|
25
|
-
addRoute(ctx, "GET", fullPath, { id, meta });
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function createRenderList(data, routes) {
|
|
29
|
-
let cacheForRoutes = renderListCache.get(routes);
|
|
30
|
-
if (!cacheForRoutes) {
|
|
31
|
-
cacheForRoutes = /* @__PURE__ */ new Map();
|
|
32
|
-
renderListCache.set(routes, cacheForRoutes);
|
|
33
|
-
}
|
|
34
|
-
const cached = cacheForRoutes.get(data.id);
|
|
35
|
-
if (cached) {
|
|
36
|
-
return cached;
|
|
37
|
-
}
|
|
38
|
-
const depth = data.id[1];
|
|
39
|
-
const list = Array.from({ length: depth });
|
|
40
|
-
let idx = depth;
|
|
41
|
-
let cursor = routes.get(data.id);
|
|
42
|
-
while (cursor) {
|
|
43
|
-
list[idx--] = cursor.component;
|
|
44
|
-
cursor = cursor.parentId !== void 0 ? routes.get(cursor.parentId) : void 0;
|
|
45
|
-
}
|
|
46
|
-
cacheForRoutes.set(data.id, list);
|
|
47
|
-
return list;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const virouSymbol = Symbol("virou");
|
|
51
|
-
function createVRouter(routes, options) {
|
|
52
|
-
const context = createRouter();
|
|
53
|
-
const routeRegistry = /* @__PURE__ */ new Map();
|
|
54
|
-
registerRoutes(context, routes, routeRegistry);
|
|
55
|
-
const activePath = ref(options?.initialPath ?? "/");
|
|
56
|
-
const snapshot = () => {
|
|
57
|
-
const matchedRoute = findRoute(context, "GET", activePath.value);
|
|
58
|
-
const _renderList = matchedRoute ? createRenderList(matchedRoute.data, routeRegistry) : null;
|
|
59
|
-
const { pathname, hash, search } = parseURL(activePath.value);
|
|
60
|
-
return {
|
|
61
|
-
fullPath: activePath.value,
|
|
62
|
-
path: pathname,
|
|
63
|
-
search,
|
|
64
|
-
hash,
|
|
65
|
-
meta: matchedRoute?.data.meta,
|
|
66
|
-
params: matchedRoute?.params,
|
|
67
|
-
_renderList
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
const route = shallowRef(snapshot());
|
|
71
|
-
const unwatch = watchEffect(() => {
|
|
72
|
-
route.value = snapshot();
|
|
73
|
-
});
|
|
74
|
-
return {
|
|
75
|
-
context,
|
|
76
|
-
routes: routeRegistry,
|
|
77
|
-
activePath,
|
|
78
|
-
route,
|
|
79
|
-
_isGlobal: options?._isGlobal ?? false,
|
|
80
|
-
_deps: 0,
|
|
81
|
-
_dispose: unwatch
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function useVRouter(...args) {
|
|
85
|
-
if (typeof args[0] !== "string") {
|
|
86
|
-
args.unshift(inject(virouSymbol, useId()));
|
|
87
|
-
}
|
|
88
|
-
const [key, routes = [], options = {}] = args;
|
|
89
|
-
if (!key || typeof key !== "string") {
|
|
90
|
-
throw new TypeError(`[virou] [useVRouter] key must be a string: ${key}`);
|
|
91
|
-
}
|
|
92
|
-
provide(virouSymbol, key);
|
|
93
|
-
const vm = getCurrentInstance();
|
|
94
|
-
if (!vm) {
|
|
95
|
-
throw new TypeError("[virou] [useVRouter] useVRouter must be called in setup()");
|
|
96
|
-
}
|
|
97
|
-
const virou = vm.proxy?.$virou;
|
|
98
|
-
if (!virou) {
|
|
99
|
-
throw new Error("[virou] [useVRouter] virou plugin not installed");
|
|
100
|
-
}
|
|
101
|
-
if (routes.length) {
|
|
102
|
-
if (virou.get(key)) {
|
|
103
|
-
throw new Error(`[virou] [useVRouter] router with key "${key}" already exists`);
|
|
104
|
-
}
|
|
105
|
-
virou.set(key, createVRouter(routes, options));
|
|
106
|
-
}
|
|
107
|
-
const router = virou.get(key);
|
|
108
|
-
if (!router) {
|
|
109
|
-
throw new Error(`[virou] [useVRouter] router with key "${key}" not found`);
|
|
110
|
-
}
|
|
111
|
-
router._deps++;
|
|
112
|
-
onScopeDispose(() => {
|
|
113
|
-
router._deps--;
|
|
114
|
-
if (router._deps === 0 && !router._isGlobal) {
|
|
115
|
-
router._dispose();
|
|
116
|
-
virou.delete(key);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
return {
|
|
120
|
-
route: router.route,
|
|
121
|
-
router: {
|
|
122
|
-
addRoute: (route) => {
|
|
123
|
-
registerRoutes(router.context, [route], router.routes);
|
|
124
|
-
},
|
|
125
|
-
replace: (path) => {
|
|
126
|
-
router.activePath.value = path;
|
|
127
|
-
},
|
|
128
|
-
_depthKey: Symbol.for(key)
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const VRouterView = defineComponent({
|
|
134
|
-
name: "VRouterView",
|
|
135
|
-
inheritAttrs: false,
|
|
136
|
-
props: {
|
|
137
|
-
routerKey: String,
|
|
138
|
-
keepAlive: { type: Boolean, default: false },
|
|
139
|
-
viewKey: { type: [String, Function] }
|
|
140
|
-
},
|
|
141
|
-
slots: Object,
|
|
142
|
-
setup(props, { slots, attrs }) {
|
|
143
|
-
const key = props.routerKey ?? inject(virouSymbol);
|
|
144
|
-
if (key === void 0) {
|
|
145
|
-
throw new Error("[virou] [VRouterView] routerKey is required");
|
|
146
|
-
}
|
|
147
|
-
const { route, router } = useVRouter(key);
|
|
148
|
-
const depth = inject(router._depthKey, 0);
|
|
149
|
-
provide(router._depthKey, depth + 1);
|
|
150
|
-
return () => {
|
|
151
|
-
const component = route.value._renderList?.[depth];
|
|
152
|
-
if (!component) {
|
|
153
|
-
return slots.default?.({ Component: null, route: route.value }) ?? null;
|
|
154
|
-
}
|
|
155
|
-
const vnodeKey = typeof props.viewKey === "function" ? props.viewKey(route.value, key) : props.viewKey ?? `${key}-${depth}-${route.value.path}`;
|
|
156
|
-
const suspenseVNode = h(
|
|
157
|
-
Suspense,
|
|
158
|
-
null,
|
|
159
|
-
{
|
|
160
|
-
default: () => h(component, { key: vnodeKey, ...attrs }),
|
|
161
|
-
fallback: () => slots.fallback?.({ route: route.value }) ?? null
|
|
162
|
-
}
|
|
163
|
-
);
|
|
164
|
-
const vnode = props.keepAlive ? h(KeepAlive, null, { default: () => suspenseVNode }) : suspenseVNode;
|
|
165
|
-
return slots.default?.({ Component: vnode, route: route.value }) ?? vnode;
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
const virou = (app, options = {}) => {
|
|
171
|
-
const { routers } = options;
|
|
172
|
-
const map = /* @__PURE__ */ new Map();
|
|
173
|
-
app.config.globalProperties.$virou = map;
|
|
174
|
-
app.component("VRouterView", VRouterView);
|
|
175
|
-
if (routers) {
|
|
176
|
-
for (const [key, router] of Object.entries(routers)) {
|
|
177
|
-
map.set(key, createVRouter(router.routes, { ...router.options, _isGlobal: true }));
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
export { VRouterView, createVRouter, useVRouter, virou, virouSymbol };
|