@route-forge/vue 1.2.1 → 1.3.0
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 +11 -10
- package/dist/index.cjs +15 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -17
- package/dist/index.d.ts +30 -17
- package/dist/index.js +15 -46
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -33,26 +33,27 @@ app.use(plugin)
|
|
|
33
33
|
|
|
34
34
|
## useForge — 核心 composable
|
|
35
35
|
|
|
36
|
-
`useForge()`
|
|
36
|
+
`useForge()` 返回 forge 实例。无 level 时返回完整 `RouteForge` 实例;传入 `level` 时内部调用 `forge.use(level, prefix?)`,自动触发 load:
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
import { useForge } from '@route-forge/vue'
|
|
40
40
|
|
|
41
|
-
// 不绑定层级 —
|
|
41
|
+
// 不绑定层级 — 返回完整 RouteForge 实例
|
|
42
42
|
const forge = useForge()
|
|
43
|
-
forge('admin', 'users.show', { user: 1 })
|
|
44
|
-
forge.
|
|
45
|
-
forge.
|
|
46
|
-
forge.onLevelLoaded('admin', () => { ... }) // 订阅 level 加载
|
|
43
|
+
forge.api('admin', 'users.show', { user: 1 }) // 通过层级 + 路由名调用
|
|
44
|
+
forge.ready().then(f => f.use('admin')) // 等待就绪后绑定层级
|
|
45
|
+
forge.use('admin') // 绑定层级,返回 BoundForge
|
|
47
46
|
|
|
48
47
|
// 绑定层级 — 自动触发 load,提供同步方法 + levelLoaded 状态
|
|
49
48
|
const forge = useForge('admin')
|
|
50
49
|
forge.level // → 'admin'
|
|
51
50
|
forge.levelLoaded // Ref<boolean>,加载完成后变为 true
|
|
52
|
-
forge('users.show', { user: 1 }) //
|
|
51
|
+
forge('users.show', { user: 1 }) // 可直接调用(= forge.api() 快捷方式)
|
|
53
52
|
forge.api('users.show', { user: 1 }) // 同上
|
|
54
|
-
forge.route('users.show', { user: 1 }) // 生成 URL
|
|
53
|
+
forge.route('users.show', { user: 1 }) // 生成 URL
|
|
55
54
|
forge.url('users.show', { user: 1 }) // route() 语义别名
|
|
55
|
+
forge.onLevelLoaded() // 等待 level 加载完成
|
|
56
|
+
forge.useRoutePrefix('users') // 追加路由名前缀
|
|
56
57
|
|
|
57
58
|
// 绑定层级 + 前缀 — 路由名自动拼接
|
|
58
59
|
const forge = useForge('admin', 'users')
|
|
@@ -67,8 +68,8 @@ forge.isLoaded('admin') // 检查缓存
|
|
|
67
68
|
forge.invalidate('admin') // 失效缓存
|
|
68
69
|
```
|
|
69
70
|
|
|
70
|
-
> **注意**:`useForge()` 无 level
|
|
71
|
-
>
|
|
71
|
+
> **注意**:`useForge()` 无 level 时返回完整 `RouteForge` 实例,包含所有方法(`route`/`url`/`hasRoute`/`getRoutes` 等)。
|
|
72
|
+
> 但 auto-discovery 可能未完成,同步方法可能抛守卫错误。建议使用 `await forge.ready()` 或 `useForgeRoute`。
|
|
72
73
|
|
|
73
74
|
### 参数智能解析
|
|
74
75
|
|
package/dist/index.cjs
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
var vue = require('vue');
|
|
4
4
|
var core = require('@route-forge/core');
|
|
5
|
-
var internal = require('@route-forge/core/internal');
|
|
6
5
|
|
|
7
6
|
// src/plugin.ts
|
|
8
7
|
var FORGE_INJECTION_KEY = /* @__PURE__ */ Symbol("route-forge");
|
|
9
8
|
function createRouteForgePlugin(options) {
|
|
10
9
|
const forge = core.createRouteForge(options);
|
|
11
10
|
return {
|
|
12
|
-
ready: forge.ready,
|
|
11
|
+
ready: forge.ready.bind(forge),
|
|
13
12
|
install(app) {
|
|
14
13
|
app.provide(FORGE_INJECTION_KEY, forge);
|
|
15
14
|
app.config.globalProperties.$forge = {
|
|
@@ -25,52 +24,22 @@ function useForge(level, prefix) {
|
|
|
25
24
|
"[route-forge/vue] useForge() must be used inside an app with createRouteForgePlugin() installed"
|
|
26
25
|
);
|
|
27
26
|
}
|
|
28
|
-
if (level
|
|
29
|
-
|
|
30
|
-
forge.load(level).then(() => {
|
|
31
|
-
levelLoaded.value = true;
|
|
32
|
-
}).catch(() => {
|
|
33
|
-
});
|
|
34
|
-
const unsub = forge.onLevelLoaded(level, () => {
|
|
35
|
-
levelLoaded.value = true;
|
|
36
|
-
unsub();
|
|
37
|
-
});
|
|
38
|
-
const callable2 = prefix ? async (name, params) => forge.api(level, await core.resolveRouteName(forge, level, prefix, name), params) : (name, params) => forge.api(level, name, params);
|
|
39
|
-
internal.defineImmutableProps(callable2, {
|
|
40
|
-
level,
|
|
41
|
-
// 未传 prefix 时不定义该属性,与 React 包行为保持一致('prefix' in forge === false)
|
|
42
|
-
...prefix !== void 0 ? { prefix } : {},
|
|
43
|
-
api: prefix ? async (name, params) => forge.api(level, await core.resolveRouteName(forge, level, prefix, name), params) : (name, params) => forge.api(level, name, params),
|
|
44
|
-
route: prefix ? (name, params) => forge.route(level, core.resolveRouteNameSync(forge, level, prefix, name), params) : (name, params) => forge.route(level, name, params),
|
|
45
|
-
url: prefix ? (name, params) => forge.route(level, core.resolveRouteNameSync(forge, level, prefix, name), params) : (name, params) => forge.route(level, name, params),
|
|
46
|
-
load: forge.load.bind(forge),
|
|
47
|
-
invalidate: forge.invalidate.bind(forge),
|
|
48
|
-
isLoaded: forge.isLoaded.bind(forge),
|
|
49
|
-
hasRoute: forge.hasRoute.bind(forge),
|
|
50
|
-
isLoading: forge.isLoading.bind(forge),
|
|
51
|
-
onLoadingChange: forge.onLoadingChange.bind(forge),
|
|
52
|
-
getRoutes: forge.getRoutes.bind(forge)
|
|
53
|
-
});
|
|
54
|
-
Object.defineProperty(callable2, "levelLoaded", {
|
|
55
|
-
value: levelLoaded,
|
|
56
|
-
writable: false,
|
|
57
|
-
enumerable: true,
|
|
58
|
-
configurable: false
|
|
59
|
-
});
|
|
60
|
-
return callable2;
|
|
27
|
+
if (level === void 0) {
|
|
28
|
+
return forge;
|
|
61
29
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
30
|
+
const bound = forge.use(level, prefix);
|
|
31
|
+
const levelLoadedRef = vue.ref(false);
|
|
32
|
+
bound.levelLoaded.then(() => {
|
|
33
|
+
levelLoadedRef.value = true;
|
|
34
|
+
}).catch(() => {
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(bound, "levelLoaded", {
|
|
37
|
+
value: levelLoadedRef,
|
|
38
|
+
writable: false,
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: false
|
|
72
41
|
});
|
|
73
|
-
return
|
|
42
|
+
return bound;
|
|
74
43
|
}
|
|
75
44
|
function useForgeApi(level, prefix) {
|
|
76
45
|
const forge = level !== void 0 ? useForge(level, prefix) : useForge();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeRoute.ts","../src/composables/useForgeByPrefix.ts"],"names":["createRouteForge","inject","ref","callable","resolveRouteName","defineImmutableProps","resolveRouteNameSync","onMounted","computed"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Vue 3 插件入口\n * @see .docs/SPEC.md §4.1.7\n *\n * 提供:\n * - 全局属性 $forge(route() 工具)\n * - inject symbol 注入 RouteForge 实例供 composable 使用\n * - useForge() / useForge(level) / useForge(level, prefix) 返回统一方法的 forge 实例\n * • 不传 level:forge(level, name, params?) 直接调用\n * • 传 level:forge(name, params?) 直接调用,自动绑定层级\n * • 传 level + prefix:forge(suffix, params?) 自动拼接 prefix\n *\n * 类型推断:\n * 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,\n * level / name / params 均自动推断,IDE 提供补全提示。\n */\n\nimport type { App, InjectionKey, Plugin, Ref } from 'vue';\nimport { inject, ref } from 'vue';\nimport {\n type ApiCallParams,\n createRouteForge,\n type ForgeInstanceTyped,\n resolveRouteName,\n resolveRouteNameSync,\n type RouteForge,\n type RouteForgeOptions,\n} from '@route-forge/core';\nimport { defineImmutableProps } from '@route-forge/core/internal';\n\nexport const FORGE_INJECTION_KEY: InjectionKey<RouteForge> = Symbol('route-forge');\n\nexport interface RouteForgePluginOptions extends RouteForgeOptions {}\n\n/** 已绑定 level — 直接调用无需 level,api/route/url 的 name 自动限定到该层级 */\nexport type BoundForgeTyped<L extends string> = import('@route-forge/core').BoundForgeTyped<L, Ref<boolean>>;\n\n/** 未绑定 level — 直接调用需要传 level(不提供 route/url/hasRoute/getRoutes 等同步方法) */\nexport type { ForgeInstanceTyped } from '@route-forge/core';\n\nexport function createRouteForgePlugin(options: RouteForgePluginOptions): Plugin<[]> & {\n ready: Promise<void>\n} {\n const forge = createRouteForge(options);\n\n return {\n ready: forge.ready,\n install(app: App) {\n app.provide(FORGE_INJECTION_KEY, forge);\n app.config.globalProperties.$forge = {\n route: (level: string, name: string, params?: Record<string, unknown>) =>\n forge.route(level, name, params),\n };\n },\n };\n}\n\n/**\n * 获取 forge 实例。\n *\n * @example\n * // 不绑定层级\n * const forge = useForge()\n * forge('admin', 'users.show', { user: 1 })\n * forge.api('admin', 'users.show')\n *\n * @example\n * // 绑定层级 — 直接调用和 api/route/url 均无需传 level\n * const forge = useForge('admin')\n * forge.level // → 'admin'\n * forge('users.show', { user: 1 })\n * forge.api('users.show')\n *\n * @example\n * // 绑定层级 + 前缀 — 路由名自动拼接\n * const forge = useForge('admin', 'users')\n * forge.level // → 'admin'\n * forge.prefix // → 'users'\n * forge('show', { user: 1 }) // → forge.api('admin', 'users.show', ...)\n * forge.api('index') // → forge.api('admin', 'users.index')\n * forge.route('show', { user: 1 }) // → forge.route('admin', 'users.show', ...)\n */\nexport function useForge<L extends string>(level: L, prefix: string): BoundForgeTyped<L>;\nexport function useForge<L extends string>(level: L): BoundForgeTyped<L>;\nexport function useForge(): ForgeInstanceTyped;\nexport function useForge(level?: string, prefix?: string): ForgeInstanceTyped | BoundForgeTyped<string> {\n const forge = inject(FORGE_INJECTION_KEY);\n if (!forge) {\n throw new Error(\n '[route-forge/vue] useForge() must be used inside an app with createRouteForgePlugin() installed',\n );\n }\n\n if (level !== undefined) {\n // 自动触发 level 加载 + 响应式 levelLoaded 状态\n const levelLoaded = ref(forge.isLoaded(level));\n forge.load(level).then(() => {\n levelLoaded.value = true;\n }).catch(() => { /* 加载失败时 levelLoaded 保持 false */\n });\n // 订阅 level 加载完成事件(兜底:如果 load() 在 ref 赋值后才完成)\n const unsub = forge.onLevelLoaded(level, () => {\n levelLoaded.value = true;\n unsub();\n });\n\n const callable = prefix\n ? async (name: string, params?: ApiCallParams) =>\n forge.api(level, await resolveRouteName(forge, level, prefix, name), params)\n : (name: string, params?: ApiCallParams) =>\n forge.api(level, name, params);\n defineImmutableProps(callable, {\n level,\n // 未传 prefix 时不定义该属性,与 React 包行为保持一致('prefix' in forge === false)\n ...(prefix !== undefined ? { prefix } : {}),\n api: prefix\n ? async (name: string, params?: ApiCallParams) =>\n forge.api(level, await resolveRouteName(forge, level, prefix, name), params)\n : (name: string, params?: ApiCallParams) => forge.api(level, name, params),\n route: prefix\n ? (name: string, params?: Record<string, unknown>) =>\n forge.route(level, resolveRouteNameSync(forge, level, prefix, name), params)\n : (name: string, params?: Record<string, unknown>) => forge.route(level, name, params),\n url: prefix\n ? (name: string, params?: Record<string, unknown>) =>\n forge.route(level, resolveRouteNameSync(forge, level, prefix, name), params)\n : (name: string, params?: Record<string, unknown>) => forge.route(level, name, params),\n load: forge.load.bind(forge),\n invalidate: forge.invalidate.bind(forge),\n isLoaded: forge.isLoaded.bind(forge),\n hasRoute: forge.hasRoute.bind(forge),\n isLoading: forge.isLoading.bind(forge),\n onLoadingChange: forge.onLoadingChange.bind(forge),\n getRoutes: forge.getRoutes.bind(forge),\n });\n // levelLoaded 需要保持响应式,不能通过 defineImmutableProps(会 Object.freeze)\n Object.defineProperty(callable, 'levelLoaded', {\n value: levelLoaded,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n return callable as unknown as BoundForgeTyped<string>;\n }\n\n const callable = (lvl: string, name: string, params?: ApiCallParams) =>\n forge.api(lvl, name, params);\n defineImmutableProps(callable, {\n api: forge.api.bind(forge),\n load: forge.load.bind(forge),\n invalidate: forge.invalidate.bind(forge),\n isLoaded: forge.isLoaded.bind(forge),\n isLoading: forge.isLoading.bind(forge),\n onLoadingChange: forge.onLoadingChange.bind(forge),\n ready: forge.ready,\n onLevelLoaded: forge.onLevelLoaded.bind(forge),\n });\n return callable as unknown as ForgeInstanceTyped;\n}\n\n\n","/**\n * useForgeApi:包装 forge.api(),自动管理 loading/error 状态\n * @see .docs/SPEC.md §4.1.7\n *\n * 支持:\n * - useForgeApi() — call(level, name, params)\n * - useForgeApi(level) — call(name, params),自动绑定层级\n * - useForgeApi(level, prefix) — call(suffix, params),自动绑定层级 + 拼接前缀\n *\n * 类型推断:\n * 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,\n * level / name / params 均自动推断,IDE 提供补全提示。\n */\n\nimport type { Ref } from 'vue';\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type {\n UseForgeApiBoundCall,\n UseForgeApiBoundReturn,\n UseForgeApiCall,\n UseForgeApiReturn,\n} from '@route-forge/core';\n\n// Vue 特化类型:pending/error 为 Ref\nexport type { UseForgeApiCall, UseForgeApiBoundCall };\nexport type UseForgeApiReturnVue = UseForgeApiReturn<Ref<boolean>, Ref<unknown>>;\nexport type UseForgeApiBoundReturnVue<L extends string> = UseForgeApiBoundReturn<L, Ref<boolean>, Ref<unknown>>;\n\n/** 不绑定层级 — call 需要传 level */\nexport function useForgeApi(): UseForgeApiReturnVue;\n/** 绑定层级 — call 无需传 level */\nexport function useForgeApi<L extends string>(level: L): UseForgeApiBoundReturnVue<L>;\n/** 绑定层级 + 前缀 — call 无需传 level,路由名自动拼接 prefix */\nexport function useForgeApi<L extends string>(level: L, prefix: string): UseForgeApiBoundReturnVue<L>;\nexport function useForgeApi(level?: string, prefix?: string): UseForgeApiReturnVue | UseForgeApiBoundReturnVue<string> {\n const forge = level !== undefined ? useForge(level, prefix as string) : useForge();\n const pending = ref(false);\n const error = ref<unknown>(null);\n\n async function call(...args: unknown[]): Promise<{ data: unknown; error: unknown }> {\n pending.value = true;\n error.value = null;\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = await (forge as any).api(...args);\n return { data, error: null };\n } catch (e) {\n error.value = e;\n return { data: undefined, error: e };\n } finally {\n pending.value = false;\n }\n }\n\n return { pending, error, call: call as any };\n}\n","/**\n * useForgeRoute:响应式 URL 生成器,内部处理 level 加载状态\n * @see .docs/SPEC.md §4.1.7\n *\n * - level 未加载时返回空字符串 ''(不抛错,模板不崩)\n * - level 加载完成后自动重新计算并返回正确 URL\n * - 用户无需关心 levelLoaded 状态,直接用即可\n */\n\nimport { computed, type ComputedRef, inject, onMounted, ref } from 'vue';\nimport { FORGE_INJECTION_KEY } from '../plugin.js';\nimport type { RouteForge } from '@route-forge/core';\n\nexport function useForgeRoute(\n level: string | (() => string),\n name: string | (() => string),\n params?: () => Record<string, unknown>,\n): ComputedRef<string> {\n const forge = inject(FORGE_INJECTION_KEY) as RouteForge;\n\n // 响应式追踪 level 加载状态(computed 依赖此 ref 触发重新计算)\n const levelLoaded = ref(forge.isLoaded(typeof level === 'function' ? level() : level));\n\n const lvl = typeof level === 'function' ? level() : level;\n if (!levelLoaded.value) {\n onMounted(() => {\n forge.load(lvl).then(() => {\n levelLoaded.value = true;\n }).catch(() => { /* 加载失败时 computed 返回 '' */\n });\n });\n }\n\n return computed(() => {\n // level 未加载 → 返回空字符串,不抛错\n if (!levelLoaded.value) return '';\n const l = typeof level === 'function' ? level() : level;\n const n = typeof name === 'function' ? name() : name;\n const p = params ? params() : undefined;\n return forge.route(l, n, p);\n });\n}\n","/**\n * useForgeByPrefix:带层级 + 名字前缀的封装,方便后续减少名称传入\n * @see .docs/SPEC.md §4.1.7\n *\n * 智能前缀解析:\n * - 传入后缀不以前缀开头 → 自动拼接 prefix.suffix\n * - 传入后缀已以前缀开头(歧义) → 优先尝试完整拼接,\n * 若不存在则视为已含前缀直接使用,均不存在则报错\n *\n * 示例(prefix = 'test'):\n * api('1') → test.1\n * api('test1.1') → test.test1.1\n * api('test.1') → 歧义:优先 test.test.1,回退 test.1\n */\n\nimport { inject } from 'vue';\nimport { FORGE_INJECTION_KEY } from '../plugin.js';\nimport {\n resolveRouteName,\n resolveRouteNameSync,\n type RouteForge,\n type UseForgeByPrefixReturn,\n} from '@route-forge/core';\n\nexport type { UseForgeByPrefixReturn };\n\nexport function useForgeByPrefix(level: string, prefix: string, separator = '.'): UseForgeByPrefixReturn {\n const forge = inject(FORGE_INJECTION_KEY) as RouteForge;\n\n return {\n api: (suffix, params) =>\n resolveRouteName(forge, level, prefix, suffix, separator).then(\n (name) => forge.api(level, name, params),\n ),\n route: (suffix, params) => {\n // level 未加载时返回空字符串,避免 resolveRouteNameSync 内部 hasRoute() 抛错\n if (!forge.isLoaded(level)) return '';\n return forge.route(level, resolveRouteNameSync(forge, level, prefix, suffix, separator), params);\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeRoute.ts","../src/composables/useForgeByPrefix.ts"],"names":["createRouteForge","inject","ref","onMounted","computed","resolveRouteName","resolveRouteNameSync"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Vue 3 插件入口\n * @see .docs/SPEC.md §4.1.7\n *\n * 提供:\n * - 全局属性 $forge(route() 工具)\n * - inject symbol 注入 RouteForge 实例供 composable 使用\n * - useForge() / useForge(level) / useForge(level, prefix) 返回统一方法的 forge 实例\n * • 不传 level:forge(level, name, params?) 直接调用\n * • 传 level:forge(name, params?) 直接调用,自动绑定层级\n * • 传 level + prefix:forge(suffix, params?) 自动拼接 prefix\n *\n * 类型推断:\n * 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,\n * level / name / params 均自动推断,IDE 提供补全提示。\n */\n\nimport type { App, InjectionKey, Plugin, Ref } from 'vue';\nimport { inject, ref } from 'vue';\nimport {\n type ApiCallParams,\n type BoundForge,\n createRouteForge,\n type RouteForge,\n type RouteForgeOptions,\n} from '@route-forge/core';\n\nexport const FORGE_INJECTION_KEY: InjectionKey<RouteForge> = Symbol('route-forge');\n\nexport interface RouteForgePluginOptions extends RouteForgeOptions {}\n\n/** Vue 特化类型:levelLoaded 为 Ref<boolean> */\nexport type VueBoundForge = BoundForge<Ref<boolean>>;\n\nexport function createRouteForgePlugin(options: RouteForgePluginOptions): Plugin<[]> & {\n ready: RouteForge['ready']\n} {\n const forge = createRouteForge(options);\n\n return {\n ready: forge.ready.bind(forge),\n install(app: App) {\n app.provide(FORGE_INJECTION_KEY, forge);\n app.config.globalProperties.$forge = {\n route: (level: string, name: string, params?: Record<string, unknown>) =>\n forge.route(level, name, params),\n };\n },\n };\n}\n\n/**\n * 获取 forge 实例。内部委托 core 的 forge.use(),仅将 levelLoaded 替换为 Vue 响应式 Ref。\n *\n * @example\n * // 不绑定层级\n * const forge = useForge()\n * forge('admin', 'users.show', { user: 1 })\n * forge.api('admin', 'users.show')\n *\n * @example\n * // 绑定层级 — 直接调用和 api/route/url 均无需传 level\n * const forge = useForge('admin')\n * forge.level // → 'admin'\n * forge.levelLoaded // Ref<boolean>\n * forge('users.show', { user: 1 })\n * forge.route('users.show', { user: 1 })\n *\n * @example\n * // 绑定层级 + 前缀 — 路由名自动拼接\n * const forge = useForge('admin', 'users')\n * forge('show', { user: 1 }) // → forge.api('admin', 'users.show', ...)\n * forge.route('show', { user: 1 }) // → forge.route('admin', 'users.show', ...)\n */\nexport function useForge<L extends string>(level: L, prefix: string): VueBoundForge;\nexport function useForge<L extends string>(level: L): VueBoundForge;\nexport function useForge(): RouteForge;\nexport function useForge(level?: string, prefix?: string): RouteForge | VueBoundForge {\n const forge = inject(FORGE_INJECTION_KEY);\n if (!forge) {\n throw new Error(\n '[route-forge/vue] useForge() must be used inside an app with createRouteForgePlugin() installed',\n );\n }\n\n if (level === undefined) {\n return forge;\n }\n\n // 委托 core 的 use(),获取 BoundForge(levelLoaded 为 Promise<void>)\n const bound = forge.use(level, prefix);\n\n // 将 levelLoaded 从 Promise<void> 替换为 Ref<boolean>\n const levelLoadedRef = ref(false);\n bound.levelLoaded.then(() => {\n levelLoadedRef.value = true;\n }).catch(() => { /* 加载失败时 levelLoaded 保持 false */ });\n\n Object.defineProperty(bound, 'levelLoaded', {\n value: levelLoadedRef,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n return bound as unknown as VueBoundForge;\n}\n","/**\n * useForgeApi:包装 forge.api(),自动管理 loading/error 状态\n * @see .docs/SPEC.md §4.1.7\n *\n * 支持:\n * - useForgeApi() — call(level, name, params)\n * - useForgeApi(level) — call(name, params),自动绑定层级\n * - useForgeApi(level, prefix) — call(suffix, params),自动绑定层级 + 拼接前缀\n *\n * 类型推断:\n * 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,\n * level / name / params 均自动推断,IDE 提供补全提示。\n */\n\nimport type { Ref } from 'vue';\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type {\n UseForgeApiBoundCall,\n UseForgeApiBoundReturn,\n UseForgeApiCall,\n UseForgeApiReturn,\n} from '@route-forge/core';\n\n// Vue 特化类型:pending/error 为 Ref\nexport type { UseForgeApiCall, UseForgeApiBoundCall };\nexport type UseForgeApiReturnVue = UseForgeApiReturn<Ref<boolean>, Ref<unknown>>;\nexport type UseForgeApiBoundReturnVue<L extends string> = UseForgeApiBoundReturn<L, Ref<boolean>, Ref<unknown>>;\n\n/** 不绑定层级 — call 需要传 level */\nexport function useForgeApi(): UseForgeApiReturnVue;\n/** 绑定层级 — call 无需传 level */\nexport function useForgeApi<L extends string>(level: L): UseForgeApiBoundReturnVue<L>;\n/** 绑定层级 + 前缀 — call 无需传 level,路由名自动拼接 prefix */\nexport function useForgeApi<L extends string>(level: L, prefix: string): UseForgeApiBoundReturnVue<L>;\nexport function useForgeApi(level?: string, prefix?: string): UseForgeApiReturnVue | UseForgeApiBoundReturnVue<string> {\n const forge = level !== undefined ? useForge(level, prefix as string) : useForge();\n const pending = ref(false);\n const error = ref<unknown>(null);\n\n async function call(...args: unknown[]): Promise<{ data: unknown; error: unknown }> {\n pending.value = true;\n error.value = null;\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = await (forge as any).api(...args);\n return { data, error: null };\n } catch (e) {\n error.value = e;\n return { data: undefined, error: e };\n } finally {\n pending.value = false;\n }\n }\n\n return { pending, error, call: call as any };\n}\n","/**\n * useForgeRoute:响应式 URL 生成器,内部处理 level 加载状态\n * @see .docs/SPEC.md §4.1.7\n *\n * - level 未加载时返回空字符串 ''(不抛错,模板不崩)\n * - level 加载完成后自动重新计算并返回正确 URL\n * - 用户无需关心 levelLoaded 状态,直接用即可\n */\n\nimport { computed, type ComputedRef, inject, onMounted, ref } from 'vue';\nimport { FORGE_INJECTION_KEY } from '../plugin.js';\nimport type { RouteForge } from '@route-forge/core';\n\nexport function useForgeRoute(\n level: string | (() => string),\n name: string | (() => string),\n params?: () => Record<string, unknown>,\n): ComputedRef<string> {\n const forge = inject(FORGE_INJECTION_KEY) as RouteForge;\n\n // 响应式追踪 level 加载状态(computed 依赖此 ref 触发重新计算)\n const levelLoaded = ref(forge.isLoaded(typeof level === 'function' ? level() : level));\n\n const lvl = typeof level === 'function' ? level() : level;\n if (!levelLoaded.value) {\n onMounted(() => {\n forge.load(lvl).then(() => {\n levelLoaded.value = true;\n }).catch(() => { /* 加载失败时 computed 返回 '' */\n });\n });\n }\n\n return computed(() => {\n // level 未加载 → 返回空字符串,不抛错\n if (!levelLoaded.value) return '';\n const l = typeof level === 'function' ? level() : level;\n const n = typeof name === 'function' ? name() : name;\n const p = params ? params() : undefined;\n return forge.route(l, n, p);\n });\n}\n","/**\n * useForgeByPrefix:带层级 + 名字前缀的封装,方便后续减少名称传入\n * @see .docs/SPEC.md §4.1.7\n *\n * 智能前缀解析:\n * - 传入后缀不以前缀开头 → 自动拼接 prefix.suffix\n * - 传入后缀已以前缀开头(歧义) → 优先尝试完整拼接,\n * 若不存在则视为已含前缀直接使用,均不存在则报错\n *\n * 示例(prefix = 'test'):\n * api('1') → test.1\n * api('test1.1') → test.test1.1\n * api('test.1') → 歧义:优先 test.test.1,回退 test.1\n */\n\nimport { inject } from 'vue';\nimport { FORGE_INJECTION_KEY } from '../plugin.js';\nimport {\n resolveRouteName,\n resolveRouteNameSync,\n type RouteForge,\n type UseForgeByPrefixReturn,\n} from '@route-forge/core';\n\nexport type { UseForgeByPrefixReturn };\n\nexport function useForgeByPrefix(level: string, prefix: string, separator = '.'): UseForgeByPrefixReturn {\n const forge = inject(FORGE_INJECTION_KEY) as RouteForge;\n\n return {\n api: (suffix, params) =>\n resolveRouteName(forge, level, prefix, suffix, separator).then(\n (name) => forge.api(level, name, params),\n ),\n route: (suffix, params) => {\n // level 未加载时返回空字符串,避免 resolveRouteNameSync 内部 hasRoute() 抛错\n if (!forge.isLoaded(level)) return '';\n return forge.route(level, resolveRouteNameSync(forge, level, prefix, suffix, separator), params);\n },\n };\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,19 +1,34 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { RouteForge, RouteForgeOptions,
|
|
3
|
-
export {
|
|
4
|
-
|
|
1
|
+
import { InjectionKey, Ref, Plugin, ComputedRef } from 'vue';
|
|
2
|
+
import { RouteForge, RouteForgeOptions, BoundForge, UseForgeApiBoundReturn, UseForgeApiReturn, UseForgeByPrefixReturn } from '@route-forge/core';
|
|
3
|
+
export { UseForgeApiBoundCall, UseForgeApiCall, UseForgeByPrefixReturn } from '@route-forge/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Vue 3 插件入口
|
|
7
|
+
* @see .docs/SPEC.md §4.1.7
|
|
8
|
+
*
|
|
9
|
+
* 提供:
|
|
10
|
+
* - 全局属性 $forge(route() 工具)
|
|
11
|
+
* - inject symbol 注入 RouteForge 实例供 composable 使用
|
|
12
|
+
* - useForge() / useForge(level) / useForge(level, prefix) 返回统一方法的 forge 实例
|
|
13
|
+
* • 不传 level:forge(level, name, params?) 直接调用
|
|
14
|
+
* • 传 level:forge(name, params?) 直接调用,自动绑定层级
|
|
15
|
+
* • 传 level + prefix:forge(suffix, params?) 自动拼接 prefix
|
|
16
|
+
*
|
|
17
|
+
* 类型推断:
|
|
18
|
+
* 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,
|
|
19
|
+
* level / name / params 均自动推断,IDE 提供补全提示。
|
|
20
|
+
*/
|
|
5
21
|
|
|
6
22
|
declare const FORGE_INJECTION_KEY: InjectionKey<RouteForge>;
|
|
7
23
|
interface RouteForgePluginOptions extends RouteForgeOptions {
|
|
8
24
|
}
|
|
9
|
-
/**
|
|
10
|
-
type
|
|
11
|
-
|
|
25
|
+
/** Vue 特化类型:levelLoaded 为 Ref<boolean> */
|
|
26
|
+
type VueBoundForge = BoundForge<Ref<boolean>>;
|
|
12
27
|
declare function createRouteForgePlugin(options: RouteForgePluginOptions): Plugin<[]> & {
|
|
13
|
-
ready:
|
|
28
|
+
ready: RouteForge['ready'];
|
|
14
29
|
};
|
|
15
30
|
/**
|
|
16
|
-
* 获取 forge
|
|
31
|
+
* 获取 forge 实例。内部委托 core 的 forge.use(),仅将 levelLoaded 替换为 Vue 响应式 Ref。
|
|
17
32
|
*
|
|
18
33
|
* @example
|
|
19
34
|
* // 不绑定层级
|
|
@@ -25,21 +40,19 @@ declare function createRouteForgePlugin(options: RouteForgePluginOptions): Plugi
|
|
|
25
40
|
* // 绑定层级 — 直接调用和 api/route/url 均无需传 level
|
|
26
41
|
* const forge = useForge('admin')
|
|
27
42
|
* forge.level // → 'admin'
|
|
43
|
+
* forge.levelLoaded // Ref<boolean>
|
|
28
44
|
* forge('users.show', { user: 1 })
|
|
29
|
-
* forge.
|
|
45
|
+
* forge.route('users.show', { user: 1 })
|
|
30
46
|
*
|
|
31
47
|
* @example
|
|
32
48
|
* // 绑定层级 + 前缀 — 路由名自动拼接
|
|
33
49
|
* const forge = useForge('admin', 'users')
|
|
34
|
-
* forge.level // → 'admin'
|
|
35
|
-
* forge.prefix // → 'users'
|
|
36
50
|
* forge('show', { user: 1 }) // → forge.api('admin', 'users.show', ...)
|
|
37
|
-
* forge.api('index') // → forge.api('admin', 'users.index')
|
|
38
51
|
* forge.route('show', { user: 1 }) // → forge.route('admin', 'users.show', ...)
|
|
39
52
|
*/
|
|
40
|
-
declare function useForge<L extends string>(level: L, prefix: string):
|
|
41
|
-
declare function useForge<L extends string>(level: L):
|
|
42
|
-
declare function useForge():
|
|
53
|
+
declare function useForge<L extends string>(level: L, prefix: string): VueBoundForge;
|
|
54
|
+
declare function useForge<L extends string>(level: L): VueBoundForge;
|
|
55
|
+
declare function useForge(): RouteForge;
|
|
43
56
|
|
|
44
57
|
/**
|
|
45
58
|
* useForgeApi:包装 forge.api(),自动管理 loading/error 状态
|
|
@@ -92,4 +105,4 @@ declare function useForgeRoute(level: string | (() => string), name: string | ((
|
|
|
92
105
|
|
|
93
106
|
declare function useForgeByPrefix(level: string, prefix: string, separator?: string): UseForgeByPrefixReturn;
|
|
94
107
|
|
|
95
|
-
export {
|
|
108
|
+
export { FORGE_INJECTION_KEY, type RouteForgePluginOptions, type UseForgeApiBoundReturnVue, type UseForgeApiReturnVue, type VueBoundForge, createRouteForgePlugin, useForge, useForgeApi, useForgeByPrefix, useForgeRoute };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,34 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { RouteForge, RouteForgeOptions,
|
|
3
|
-
export {
|
|
4
|
-
|
|
1
|
+
import { InjectionKey, Ref, Plugin, ComputedRef } from 'vue';
|
|
2
|
+
import { RouteForge, RouteForgeOptions, BoundForge, UseForgeApiBoundReturn, UseForgeApiReturn, UseForgeByPrefixReturn } from '@route-forge/core';
|
|
3
|
+
export { UseForgeApiBoundCall, UseForgeApiCall, UseForgeByPrefixReturn } from '@route-forge/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Vue 3 插件入口
|
|
7
|
+
* @see .docs/SPEC.md §4.1.7
|
|
8
|
+
*
|
|
9
|
+
* 提供:
|
|
10
|
+
* - 全局属性 $forge(route() 工具)
|
|
11
|
+
* - inject symbol 注入 RouteForge 实例供 composable 使用
|
|
12
|
+
* - useForge() / useForge(level) / useForge(level, prefix) 返回统一方法的 forge 实例
|
|
13
|
+
* • 不传 level:forge(level, name, params?) 直接调用
|
|
14
|
+
* • 传 level:forge(name, params?) 直接调用,自动绑定层级
|
|
15
|
+
* • 传 level + prefix:forge(suffix, params?) 自动拼接 prefix
|
|
16
|
+
*
|
|
17
|
+
* 类型推断:
|
|
18
|
+
* 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,
|
|
19
|
+
* level / name / params 均自动推断,IDE 提供补全提示。
|
|
20
|
+
*/
|
|
5
21
|
|
|
6
22
|
declare const FORGE_INJECTION_KEY: InjectionKey<RouteForge>;
|
|
7
23
|
interface RouteForgePluginOptions extends RouteForgeOptions {
|
|
8
24
|
}
|
|
9
|
-
/**
|
|
10
|
-
type
|
|
11
|
-
|
|
25
|
+
/** Vue 特化类型:levelLoaded 为 Ref<boolean> */
|
|
26
|
+
type VueBoundForge = BoundForge<Ref<boolean>>;
|
|
12
27
|
declare function createRouteForgePlugin(options: RouteForgePluginOptions): Plugin<[]> & {
|
|
13
|
-
ready:
|
|
28
|
+
ready: RouteForge['ready'];
|
|
14
29
|
};
|
|
15
30
|
/**
|
|
16
|
-
* 获取 forge
|
|
31
|
+
* 获取 forge 实例。内部委托 core 的 forge.use(),仅将 levelLoaded 替换为 Vue 响应式 Ref。
|
|
17
32
|
*
|
|
18
33
|
* @example
|
|
19
34
|
* // 不绑定层级
|
|
@@ -25,21 +40,19 @@ declare function createRouteForgePlugin(options: RouteForgePluginOptions): Plugi
|
|
|
25
40
|
* // 绑定层级 — 直接调用和 api/route/url 均无需传 level
|
|
26
41
|
* const forge = useForge('admin')
|
|
27
42
|
* forge.level // → 'admin'
|
|
43
|
+
* forge.levelLoaded // Ref<boolean>
|
|
28
44
|
* forge('users.show', { user: 1 })
|
|
29
|
-
* forge.
|
|
45
|
+
* forge.route('users.show', { user: 1 })
|
|
30
46
|
*
|
|
31
47
|
* @example
|
|
32
48
|
* // 绑定层级 + 前缀 — 路由名自动拼接
|
|
33
49
|
* const forge = useForge('admin', 'users')
|
|
34
|
-
* forge.level // → 'admin'
|
|
35
|
-
* forge.prefix // → 'users'
|
|
36
50
|
* forge('show', { user: 1 }) // → forge.api('admin', 'users.show', ...)
|
|
37
|
-
* forge.api('index') // → forge.api('admin', 'users.index')
|
|
38
51
|
* forge.route('show', { user: 1 }) // → forge.route('admin', 'users.show', ...)
|
|
39
52
|
*/
|
|
40
|
-
declare function useForge<L extends string>(level: L, prefix: string):
|
|
41
|
-
declare function useForge<L extends string>(level: L):
|
|
42
|
-
declare function useForge():
|
|
53
|
+
declare function useForge<L extends string>(level: L, prefix: string): VueBoundForge;
|
|
54
|
+
declare function useForge<L extends string>(level: L): VueBoundForge;
|
|
55
|
+
declare function useForge(): RouteForge;
|
|
43
56
|
|
|
44
57
|
/**
|
|
45
58
|
* useForgeApi:包装 forge.api(),自动管理 loading/error 状态
|
|
@@ -92,4 +105,4 @@ declare function useForgeRoute(level: string | (() => string), name: string | ((
|
|
|
92
105
|
|
|
93
106
|
declare function useForgeByPrefix(level: string, prefix: string, separator?: string): UseForgeByPrefixReturn;
|
|
94
107
|
|
|
95
|
-
export {
|
|
108
|
+
export { FORGE_INJECTION_KEY, type RouteForgePluginOptions, type UseForgeApiBoundReturnVue, type UseForgeApiReturnVue, type VueBoundForge, createRouteForgePlugin, useForge, useForgeApi, useForgeByPrefix, useForgeRoute };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { inject, ref, onMounted, computed } from 'vue';
|
|
2
2
|
import { createRouteForge, resolveRouteNameSync, resolveRouteName } from '@route-forge/core';
|
|
3
|
-
import { defineImmutableProps } from '@route-forge/core/internal';
|
|
4
3
|
|
|
5
4
|
// src/plugin.ts
|
|
6
5
|
var FORGE_INJECTION_KEY = /* @__PURE__ */ Symbol("route-forge");
|
|
7
6
|
function createRouteForgePlugin(options) {
|
|
8
7
|
const forge = createRouteForge(options);
|
|
9
8
|
return {
|
|
10
|
-
ready: forge.ready,
|
|
9
|
+
ready: forge.ready.bind(forge),
|
|
11
10
|
install(app) {
|
|
12
11
|
app.provide(FORGE_INJECTION_KEY, forge);
|
|
13
12
|
app.config.globalProperties.$forge = {
|
|
@@ -23,52 +22,22 @@ function useForge(level, prefix) {
|
|
|
23
22
|
"[route-forge/vue] useForge() must be used inside an app with createRouteForgePlugin() installed"
|
|
24
23
|
);
|
|
25
24
|
}
|
|
26
|
-
if (level
|
|
27
|
-
|
|
28
|
-
forge.load(level).then(() => {
|
|
29
|
-
levelLoaded.value = true;
|
|
30
|
-
}).catch(() => {
|
|
31
|
-
});
|
|
32
|
-
const unsub = forge.onLevelLoaded(level, () => {
|
|
33
|
-
levelLoaded.value = true;
|
|
34
|
-
unsub();
|
|
35
|
-
});
|
|
36
|
-
const callable2 = prefix ? async (name, params) => forge.api(level, await resolveRouteName(forge, level, prefix, name), params) : (name, params) => forge.api(level, name, params);
|
|
37
|
-
defineImmutableProps(callable2, {
|
|
38
|
-
level,
|
|
39
|
-
// 未传 prefix 时不定义该属性,与 React 包行为保持一致('prefix' in forge === false)
|
|
40
|
-
...prefix !== void 0 ? { prefix } : {},
|
|
41
|
-
api: prefix ? async (name, params) => forge.api(level, await resolveRouteName(forge, level, prefix, name), params) : (name, params) => forge.api(level, name, params),
|
|
42
|
-
route: prefix ? (name, params) => forge.route(level, resolveRouteNameSync(forge, level, prefix, name), params) : (name, params) => forge.route(level, name, params),
|
|
43
|
-
url: prefix ? (name, params) => forge.route(level, resolveRouteNameSync(forge, level, prefix, name), params) : (name, params) => forge.route(level, name, params),
|
|
44
|
-
load: forge.load.bind(forge),
|
|
45
|
-
invalidate: forge.invalidate.bind(forge),
|
|
46
|
-
isLoaded: forge.isLoaded.bind(forge),
|
|
47
|
-
hasRoute: forge.hasRoute.bind(forge),
|
|
48
|
-
isLoading: forge.isLoading.bind(forge),
|
|
49
|
-
onLoadingChange: forge.onLoadingChange.bind(forge),
|
|
50
|
-
getRoutes: forge.getRoutes.bind(forge)
|
|
51
|
-
});
|
|
52
|
-
Object.defineProperty(callable2, "levelLoaded", {
|
|
53
|
-
value: levelLoaded,
|
|
54
|
-
writable: false,
|
|
55
|
-
enumerable: true,
|
|
56
|
-
configurable: false
|
|
57
|
-
});
|
|
58
|
-
return callable2;
|
|
25
|
+
if (level === void 0) {
|
|
26
|
+
return forge;
|
|
59
27
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
28
|
+
const bound = forge.use(level, prefix);
|
|
29
|
+
const levelLoadedRef = ref(false);
|
|
30
|
+
bound.levelLoaded.then(() => {
|
|
31
|
+
levelLoadedRef.value = true;
|
|
32
|
+
}).catch(() => {
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(bound, "levelLoaded", {
|
|
35
|
+
value: levelLoadedRef,
|
|
36
|
+
writable: false,
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: false
|
|
70
39
|
});
|
|
71
|
-
return
|
|
40
|
+
return bound;
|
|
72
41
|
}
|
|
73
42
|
function useForgeApi(level, prefix) {
|
|
74
43
|
const forge = level !== void 0 ? useForge(level, prefix) : useForge();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeRoute.ts","../src/composables/useForgeByPrefix.ts"],"names":["callable","ref","inject","resolveRouteName","resolveRouteNameSync"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Vue 3 插件入口\n * @see .docs/SPEC.md §4.1.7\n *\n * 提供:\n * - 全局属性 $forge(route() 工具)\n * - inject symbol 注入 RouteForge 实例供 composable 使用\n * - useForge() / useForge(level) / useForge(level, prefix) 返回统一方法的 forge 实例\n * • 不传 level:forge(level, name, params?) 直接调用\n * • 传 level:forge(name, params?) 直接调用,自动绑定层级\n * • 传 level + prefix:forge(suffix, params?) 自动拼接 prefix\n *\n * 类型推断:\n * 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,\n * level / name / params 均自动推断,IDE 提供补全提示。\n */\n\nimport type { App, InjectionKey, Plugin, Ref } from 'vue';\nimport { inject, ref } from 'vue';\nimport {\n type ApiCallParams,\n createRouteForge,\n type ForgeInstanceTyped,\n resolveRouteName,\n resolveRouteNameSync,\n type RouteForge,\n type RouteForgeOptions,\n} from '@route-forge/core';\nimport { defineImmutableProps } from '@route-forge/core/internal';\n\nexport const FORGE_INJECTION_KEY: InjectionKey<RouteForge> = Symbol('route-forge');\n\nexport interface RouteForgePluginOptions extends RouteForgeOptions {}\n\n/** 已绑定 level — 直接调用无需 level,api/route/url 的 name 自动限定到该层级 */\nexport type BoundForgeTyped<L extends string> = import('@route-forge/core').BoundForgeTyped<L, Ref<boolean>>;\n\n/** 未绑定 level — 直接调用需要传 level(不提供 route/url/hasRoute/getRoutes 等同步方法) */\nexport type { ForgeInstanceTyped } from '@route-forge/core';\n\nexport function createRouteForgePlugin(options: RouteForgePluginOptions): Plugin<[]> & {\n ready: Promise<void>\n} {\n const forge = createRouteForge(options);\n\n return {\n ready: forge.ready,\n install(app: App) {\n app.provide(FORGE_INJECTION_KEY, forge);\n app.config.globalProperties.$forge = {\n route: (level: string, name: string, params?: Record<string, unknown>) =>\n forge.route(level, name, params),\n };\n },\n };\n}\n\n/**\n * 获取 forge 实例。\n *\n * @example\n * // 不绑定层级\n * const forge = useForge()\n * forge('admin', 'users.show', { user: 1 })\n * forge.api('admin', 'users.show')\n *\n * @example\n * // 绑定层级 — 直接调用和 api/route/url 均无需传 level\n * const forge = useForge('admin')\n * forge.level // → 'admin'\n * forge('users.show', { user: 1 })\n * forge.api('users.show')\n *\n * @example\n * // 绑定层级 + 前缀 — 路由名自动拼接\n * const forge = useForge('admin', 'users')\n * forge.level // → 'admin'\n * forge.prefix // → 'users'\n * forge('show', { user: 1 }) // → forge.api('admin', 'users.show', ...)\n * forge.api('index') // → forge.api('admin', 'users.index')\n * forge.route('show', { user: 1 }) // → forge.route('admin', 'users.show', ...)\n */\nexport function useForge<L extends string>(level: L, prefix: string): BoundForgeTyped<L>;\nexport function useForge<L extends string>(level: L): BoundForgeTyped<L>;\nexport function useForge(): ForgeInstanceTyped;\nexport function useForge(level?: string, prefix?: string): ForgeInstanceTyped | BoundForgeTyped<string> {\n const forge = inject(FORGE_INJECTION_KEY);\n if (!forge) {\n throw new Error(\n '[route-forge/vue] useForge() must be used inside an app with createRouteForgePlugin() installed',\n );\n }\n\n if (level !== undefined) {\n // 自动触发 level 加载 + 响应式 levelLoaded 状态\n const levelLoaded = ref(forge.isLoaded(level));\n forge.load(level).then(() => {\n levelLoaded.value = true;\n }).catch(() => { /* 加载失败时 levelLoaded 保持 false */\n });\n // 订阅 level 加载完成事件(兜底:如果 load() 在 ref 赋值后才完成)\n const unsub = forge.onLevelLoaded(level, () => {\n levelLoaded.value = true;\n unsub();\n });\n\n const callable = prefix\n ? async (name: string, params?: ApiCallParams) =>\n forge.api(level, await resolveRouteName(forge, level, prefix, name), params)\n : (name: string, params?: ApiCallParams) =>\n forge.api(level, name, params);\n defineImmutableProps(callable, {\n level,\n // 未传 prefix 时不定义该属性,与 React 包行为保持一致('prefix' in forge === false)\n ...(prefix !== undefined ? { prefix } : {}),\n api: prefix\n ? async (name: string, params?: ApiCallParams) =>\n forge.api(level, await resolveRouteName(forge, level, prefix, name), params)\n : (name: string, params?: ApiCallParams) => forge.api(level, name, params),\n route: prefix\n ? (name: string, params?: Record<string, unknown>) =>\n forge.route(level, resolveRouteNameSync(forge, level, prefix, name), params)\n : (name: string, params?: Record<string, unknown>) => forge.route(level, name, params),\n url: prefix\n ? (name: string, params?: Record<string, unknown>) =>\n forge.route(level, resolveRouteNameSync(forge, level, prefix, name), params)\n : (name: string, params?: Record<string, unknown>) => forge.route(level, name, params),\n load: forge.load.bind(forge),\n invalidate: forge.invalidate.bind(forge),\n isLoaded: forge.isLoaded.bind(forge),\n hasRoute: forge.hasRoute.bind(forge),\n isLoading: forge.isLoading.bind(forge),\n onLoadingChange: forge.onLoadingChange.bind(forge),\n getRoutes: forge.getRoutes.bind(forge),\n });\n // levelLoaded 需要保持响应式,不能通过 defineImmutableProps(会 Object.freeze)\n Object.defineProperty(callable, 'levelLoaded', {\n value: levelLoaded,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n return callable as unknown as BoundForgeTyped<string>;\n }\n\n const callable = (lvl: string, name: string, params?: ApiCallParams) =>\n forge.api(lvl, name, params);\n defineImmutableProps(callable, {\n api: forge.api.bind(forge),\n load: forge.load.bind(forge),\n invalidate: forge.invalidate.bind(forge),\n isLoaded: forge.isLoaded.bind(forge),\n isLoading: forge.isLoading.bind(forge),\n onLoadingChange: forge.onLoadingChange.bind(forge),\n ready: forge.ready,\n onLevelLoaded: forge.onLevelLoaded.bind(forge),\n });\n return callable as unknown as ForgeInstanceTyped;\n}\n\n\n","/**\n * useForgeApi:包装 forge.api(),自动管理 loading/error 状态\n * @see .docs/SPEC.md §4.1.7\n *\n * 支持:\n * - useForgeApi() — call(level, name, params)\n * - useForgeApi(level) — call(name, params),自动绑定层级\n * - useForgeApi(level, prefix) — call(suffix, params),自动绑定层级 + 拼接前缀\n *\n * 类型推断:\n * 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,\n * level / name / params 均自动推断,IDE 提供补全提示。\n */\n\nimport type { Ref } from 'vue';\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type {\n UseForgeApiBoundCall,\n UseForgeApiBoundReturn,\n UseForgeApiCall,\n UseForgeApiReturn,\n} from '@route-forge/core';\n\n// Vue 特化类型:pending/error 为 Ref\nexport type { UseForgeApiCall, UseForgeApiBoundCall };\nexport type UseForgeApiReturnVue = UseForgeApiReturn<Ref<boolean>, Ref<unknown>>;\nexport type UseForgeApiBoundReturnVue<L extends string> = UseForgeApiBoundReturn<L, Ref<boolean>, Ref<unknown>>;\n\n/** 不绑定层级 — call 需要传 level */\nexport function useForgeApi(): UseForgeApiReturnVue;\n/** 绑定层级 — call 无需传 level */\nexport function useForgeApi<L extends string>(level: L): UseForgeApiBoundReturnVue<L>;\n/** 绑定层级 + 前缀 — call 无需传 level,路由名自动拼接 prefix */\nexport function useForgeApi<L extends string>(level: L, prefix: string): UseForgeApiBoundReturnVue<L>;\nexport function useForgeApi(level?: string, prefix?: string): UseForgeApiReturnVue | UseForgeApiBoundReturnVue<string> {\n const forge = level !== undefined ? useForge(level, prefix as string) : useForge();\n const pending = ref(false);\n const error = ref<unknown>(null);\n\n async function call(...args: unknown[]): Promise<{ data: unknown; error: unknown }> {\n pending.value = true;\n error.value = null;\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = await (forge as any).api(...args);\n return { data, error: null };\n } catch (e) {\n error.value = e;\n return { data: undefined, error: e };\n } finally {\n pending.value = false;\n }\n }\n\n return { pending, error, call: call as any };\n}\n","/**\n * useForgeRoute:响应式 URL 生成器,内部处理 level 加载状态\n * @see .docs/SPEC.md §4.1.7\n *\n * - level 未加载时返回空字符串 ''(不抛错,模板不崩)\n * - level 加载完成后自动重新计算并返回正确 URL\n * - 用户无需关心 levelLoaded 状态,直接用即可\n */\n\nimport { computed, type ComputedRef, inject, onMounted, ref } from 'vue';\nimport { FORGE_INJECTION_KEY } from '../plugin.js';\nimport type { RouteForge } from '@route-forge/core';\n\nexport function useForgeRoute(\n level: string | (() => string),\n name: string | (() => string),\n params?: () => Record<string, unknown>,\n): ComputedRef<string> {\n const forge = inject(FORGE_INJECTION_KEY) as RouteForge;\n\n // 响应式追踪 level 加载状态(computed 依赖此 ref 触发重新计算)\n const levelLoaded = ref(forge.isLoaded(typeof level === 'function' ? level() : level));\n\n const lvl = typeof level === 'function' ? level() : level;\n if (!levelLoaded.value) {\n onMounted(() => {\n forge.load(lvl).then(() => {\n levelLoaded.value = true;\n }).catch(() => { /* 加载失败时 computed 返回 '' */\n });\n });\n }\n\n return computed(() => {\n // level 未加载 → 返回空字符串,不抛错\n if (!levelLoaded.value) return '';\n const l = typeof level === 'function' ? level() : level;\n const n = typeof name === 'function' ? name() : name;\n const p = params ? params() : undefined;\n return forge.route(l, n, p);\n });\n}\n","/**\n * useForgeByPrefix:带层级 + 名字前缀的封装,方便后续减少名称传入\n * @see .docs/SPEC.md §4.1.7\n *\n * 智能前缀解析:\n * - 传入后缀不以前缀开头 → 自动拼接 prefix.suffix\n * - 传入后缀已以前缀开头(歧义) → 优先尝试完整拼接,\n * 若不存在则视为已含前缀直接使用,均不存在则报错\n *\n * 示例(prefix = 'test'):\n * api('1') → test.1\n * api('test1.1') → test.test1.1\n * api('test.1') → 歧义:优先 test.test.1,回退 test.1\n */\n\nimport { inject } from 'vue';\nimport { FORGE_INJECTION_KEY } from '../plugin.js';\nimport {\n resolveRouteName,\n resolveRouteNameSync,\n type RouteForge,\n type UseForgeByPrefixReturn,\n} from '@route-forge/core';\n\nexport type { UseForgeByPrefixReturn };\n\nexport function useForgeByPrefix(level: string, prefix: string, separator = '.'): UseForgeByPrefixReturn {\n const forge = inject(FORGE_INJECTION_KEY) as RouteForge;\n\n return {\n api: (suffix, params) =>\n resolveRouteName(forge, level, prefix, suffix, separator).then(\n (name) => forge.api(level, name, params),\n ),\n route: (suffix, params) => {\n // level 未加载时返回空字符串,避免 resolveRouteNameSync 内部 hasRoute() 抛错\n if (!forge.isLoaded(level)) return '';\n return forge.route(level, resolveRouteNameSync(forge, level, prefix, suffix, separator), params);\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeRoute.ts","../src/composables/useForgeByPrefix.ts"],"names":["ref","inject"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Vue 3 插件入口\n * @see .docs/SPEC.md §4.1.7\n *\n * 提供:\n * - 全局属性 $forge(route() 工具)\n * - inject symbol 注入 RouteForge 实例供 composable 使用\n * - useForge() / useForge(level) / useForge(level, prefix) 返回统一方法的 forge 实例\n * • 不传 level:forge(level, name, params?) 直接调用\n * • 传 level:forge(name, params?) 直接调用,自动绑定层级\n * • 传 level + prefix:forge(suffix, params?) 自动拼接 prefix\n *\n * 类型推断:\n * 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,\n * level / name / params 均自动推断,IDE 提供补全提示。\n */\n\nimport type { App, InjectionKey, Plugin, Ref } from 'vue';\nimport { inject, ref } from 'vue';\nimport {\n type ApiCallParams,\n type BoundForge,\n createRouteForge,\n type RouteForge,\n type RouteForgeOptions,\n} from '@route-forge/core';\n\nexport const FORGE_INJECTION_KEY: InjectionKey<RouteForge> = Symbol('route-forge');\n\nexport interface RouteForgePluginOptions extends RouteForgeOptions {}\n\n/** Vue 特化类型:levelLoaded 为 Ref<boolean> */\nexport type VueBoundForge = BoundForge<Ref<boolean>>;\n\nexport function createRouteForgePlugin(options: RouteForgePluginOptions): Plugin<[]> & {\n ready: RouteForge['ready']\n} {\n const forge = createRouteForge(options);\n\n return {\n ready: forge.ready.bind(forge),\n install(app: App) {\n app.provide(FORGE_INJECTION_KEY, forge);\n app.config.globalProperties.$forge = {\n route: (level: string, name: string, params?: Record<string, unknown>) =>\n forge.route(level, name, params),\n };\n },\n };\n}\n\n/**\n * 获取 forge 实例。内部委托 core 的 forge.use(),仅将 levelLoaded 替换为 Vue 响应式 Ref。\n *\n * @example\n * // 不绑定层级\n * const forge = useForge()\n * forge('admin', 'users.show', { user: 1 })\n * forge.api('admin', 'users.show')\n *\n * @example\n * // 绑定层级 — 直接调用和 api/route/url 均无需传 level\n * const forge = useForge('admin')\n * forge.level // → 'admin'\n * forge.levelLoaded // Ref<boolean>\n * forge('users.show', { user: 1 })\n * forge.route('users.show', { user: 1 })\n *\n * @example\n * // 绑定层级 + 前缀 — 路由名自动拼接\n * const forge = useForge('admin', 'users')\n * forge('show', { user: 1 }) // → forge.api('admin', 'users.show', ...)\n * forge.route('show', { user: 1 }) // → forge.route('admin', 'users.show', ...)\n */\nexport function useForge<L extends string>(level: L, prefix: string): VueBoundForge;\nexport function useForge<L extends string>(level: L): VueBoundForge;\nexport function useForge(): RouteForge;\nexport function useForge(level?: string, prefix?: string): RouteForge | VueBoundForge {\n const forge = inject(FORGE_INJECTION_KEY);\n if (!forge) {\n throw new Error(\n '[route-forge/vue] useForge() must be used inside an app with createRouteForgePlugin() installed',\n );\n }\n\n if (level === undefined) {\n return forge;\n }\n\n // 委托 core 的 use(),获取 BoundForge(levelLoaded 为 Promise<void>)\n const bound = forge.use(level, prefix);\n\n // 将 levelLoaded 从 Promise<void> 替换为 Ref<boolean>\n const levelLoadedRef = ref(false);\n bound.levelLoaded.then(() => {\n levelLoadedRef.value = true;\n }).catch(() => { /* 加载失败时 levelLoaded 保持 false */ });\n\n Object.defineProperty(bound, 'levelLoaded', {\n value: levelLoadedRef,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n return bound as unknown as VueBoundForge;\n}\n","/**\n * useForgeApi:包装 forge.api(),自动管理 loading/error 状态\n * @see .docs/SPEC.md §4.1.7\n *\n * 支持:\n * - useForgeApi() — call(level, name, params)\n * - useForgeApi(level) — call(name, params),自动绑定层级\n * - useForgeApi(level, prefix) — call(suffix, params),自动绑定层级 + 拼接前缀\n *\n * 类型推断:\n * 当 ForgeRouteMap 通过 codegen 或 module augmentation 定义时,\n * level / name / params 均自动推断,IDE 提供补全提示。\n */\n\nimport type { Ref } from 'vue';\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type {\n UseForgeApiBoundCall,\n UseForgeApiBoundReturn,\n UseForgeApiCall,\n UseForgeApiReturn,\n} from '@route-forge/core';\n\n// Vue 特化类型:pending/error 为 Ref\nexport type { UseForgeApiCall, UseForgeApiBoundCall };\nexport type UseForgeApiReturnVue = UseForgeApiReturn<Ref<boolean>, Ref<unknown>>;\nexport type UseForgeApiBoundReturnVue<L extends string> = UseForgeApiBoundReturn<L, Ref<boolean>, Ref<unknown>>;\n\n/** 不绑定层级 — call 需要传 level */\nexport function useForgeApi(): UseForgeApiReturnVue;\n/** 绑定层级 — call 无需传 level */\nexport function useForgeApi<L extends string>(level: L): UseForgeApiBoundReturnVue<L>;\n/** 绑定层级 + 前缀 — call 无需传 level,路由名自动拼接 prefix */\nexport function useForgeApi<L extends string>(level: L, prefix: string): UseForgeApiBoundReturnVue<L>;\nexport function useForgeApi(level?: string, prefix?: string): UseForgeApiReturnVue | UseForgeApiBoundReturnVue<string> {\n const forge = level !== undefined ? useForge(level, prefix as string) : useForge();\n const pending = ref(false);\n const error = ref<unknown>(null);\n\n async function call(...args: unknown[]): Promise<{ data: unknown; error: unknown }> {\n pending.value = true;\n error.value = null;\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = await (forge as any).api(...args);\n return { data, error: null };\n } catch (e) {\n error.value = e;\n return { data: undefined, error: e };\n } finally {\n pending.value = false;\n }\n }\n\n return { pending, error, call: call as any };\n}\n","/**\n * useForgeRoute:响应式 URL 生成器,内部处理 level 加载状态\n * @see .docs/SPEC.md §4.1.7\n *\n * - level 未加载时返回空字符串 ''(不抛错,模板不崩)\n * - level 加载完成后自动重新计算并返回正确 URL\n * - 用户无需关心 levelLoaded 状态,直接用即可\n */\n\nimport { computed, type ComputedRef, inject, onMounted, ref } from 'vue';\nimport { FORGE_INJECTION_KEY } from '../plugin.js';\nimport type { RouteForge } from '@route-forge/core';\n\nexport function useForgeRoute(\n level: string | (() => string),\n name: string | (() => string),\n params?: () => Record<string, unknown>,\n): ComputedRef<string> {\n const forge = inject(FORGE_INJECTION_KEY) as RouteForge;\n\n // 响应式追踪 level 加载状态(computed 依赖此 ref 触发重新计算)\n const levelLoaded = ref(forge.isLoaded(typeof level === 'function' ? level() : level));\n\n const lvl = typeof level === 'function' ? level() : level;\n if (!levelLoaded.value) {\n onMounted(() => {\n forge.load(lvl).then(() => {\n levelLoaded.value = true;\n }).catch(() => { /* 加载失败时 computed 返回 '' */\n });\n });\n }\n\n return computed(() => {\n // level 未加载 → 返回空字符串,不抛错\n if (!levelLoaded.value) return '';\n const l = typeof level === 'function' ? level() : level;\n const n = typeof name === 'function' ? name() : name;\n const p = params ? params() : undefined;\n return forge.route(l, n, p);\n });\n}\n","/**\n * useForgeByPrefix:带层级 + 名字前缀的封装,方便后续减少名称传入\n * @see .docs/SPEC.md §4.1.7\n *\n * 智能前缀解析:\n * - 传入后缀不以前缀开头 → 自动拼接 prefix.suffix\n * - 传入后缀已以前缀开头(歧义) → 优先尝试完整拼接,\n * 若不存在则视为已含前缀直接使用,均不存在则报错\n *\n * 示例(prefix = 'test'):\n * api('1') → test.1\n * api('test1.1') → test.test1.1\n * api('test.1') → 歧义:优先 test.test.1,回退 test.1\n */\n\nimport { inject } from 'vue';\nimport { FORGE_INJECTION_KEY } from '../plugin.js';\nimport {\n resolveRouteName,\n resolveRouteNameSync,\n type RouteForge,\n type UseForgeByPrefixReturn,\n} from '@route-forge/core';\n\nexport type { UseForgeByPrefixReturn };\n\nexport function useForgeByPrefix(level: string, prefix: string, separator = '.'): UseForgeByPrefixReturn {\n const forge = inject(FORGE_INJECTION_KEY) as RouteForge;\n\n return {\n api: (suffix, params) =>\n resolveRouteName(forge, level, prefix, suffix, separator).then(\n (name) => forge.api(level, name, params),\n ),\n route: (suffix, params) => {\n // level 未加载时返回空字符串,避免 resolveRouteNameSync 内部 hasRoute() 抛错\n if (!forge.isLoaded(level)) return '';\n return forge.route(level, resolveRouteNameSync(forge, level, prefix, suffix, separator), params);\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@route-forge/vue",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Route Forge 的 Vue 3 集成:插件 + composable(useForge/useForgeApi/useForgeLevel/useForgeRoute/useForgeByPrefix)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "阿杰很厉害 <506907958@qq.com>",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"vue": "^3.4.0"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@route-forge/core": "1.
|
|
43
|
+
"@route-forge/core": "1.3.0"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|