@route-forge/vue 2.0.0 → 2.1.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/dist/index.cjs +3 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -37,7 +37,7 @@ function useForge(level, prefix) {
|
|
|
37
37
|
value: levelLoadedRef,
|
|
38
38
|
writable: false,
|
|
39
39
|
enumerable: true,
|
|
40
|
-
configurable:
|
|
40
|
+
configurable: true
|
|
41
41
|
});
|
|
42
42
|
return bound;
|
|
43
43
|
}
|
|
@@ -74,8 +74,8 @@ function warnRenderError(error) {
|
|
|
74
74
|
}
|
|
75
75
|
function useForgeRoute(level, name, params) {
|
|
76
76
|
const forge = vue.inject(FORGE_INJECTION_KEY);
|
|
77
|
-
const levelLoaded = vue.ref(forge.isLoaded(typeof level === "function" ? level() : level));
|
|
78
77
|
const lvl = typeof level === "function" ? level() : level;
|
|
78
|
+
const levelLoaded = vue.ref(forge.isLoaded(lvl));
|
|
79
79
|
if (!levelLoaded.value) {
|
|
80
80
|
vue.onMounted(() => {
|
|
81
81
|
forge.load(lvl).then(() => {
|
|
@@ -86,11 +86,10 @@ function useForgeRoute(level, name, params) {
|
|
|
86
86
|
}
|
|
87
87
|
return vue.computed(() => {
|
|
88
88
|
if (!levelLoaded.value) return "";
|
|
89
|
-
const l = typeof level === "function" ? level() : level;
|
|
90
89
|
const n = typeof name === "function" ? name() : name;
|
|
91
90
|
const p = params ? params() : void 0;
|
|
92
91
|
try {
|
|
93
|
-
return forge.route(
|
|
92
|
+
return forge.route(lvl, n, p);
|
|
94
93
|
} catch (e) {
|
|
95
94
|
warnRenderError(e);
|
|
96
95
|
return "";
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeRoute.ts"],"names":["createRouteForge","inject","ref","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 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 * pending 采用引用计数:并发多个 call 时,全部完成才置 false\n * (先完成的 call 不再把其他在途请求的 pending 提前清掉)。\n */\n\nimport type { Ref } from 'vue';\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type {\n BoundForge,\n RouteForge,\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 bound = level !== undefined ? useForge(level, prefix as string) : undefined;\n const unbound = bound === undefined ? useForge() : undefined;\n const pending = ref(false);\n const error = ref<unknown>(null);\n // 并发计数:setup 闭包变量(组件实例生命周期存活)\n let inflight = 0;\n\n async function call(...args: unknown[]): Promise<{ data: unknown; error: unknown }> {\n inflight++;\n pending.value = true;\n error.value = null;\n try {\n // 按绑定形态分发:bound 走 BoundForge.api(name, params),unbound 走 RouteForge.api(level, name, params)\n // (窄断言替代 as any:重载签名已保证参数形状,此处仅消除联合类型/框架特化类型的分支歧义)\n const data = bound !== undefined\n ? await (bound as unknown as BoundForge).api(args[0] as string, args[1] as never)\n : await (unbound as RouteForge).api(args[0] as string, args[1] as string, args[2] as never);\n return { data, error: null };\n } catch (e) {\n error.value = e;\n return { data: undefined, error: e };\n } finally {\n inflight--;\n pending.value = inflight > 0;\n }\n }\n\n return { pending, error, call: call as unknown as UseForgeApiCall };\n}\n","/**\n * useForgeRoute:响应式 URL 生成器,内部处理 level 加载状态\n * @see .docs/SPEC.md §4.1.7\n *\n * - level 未加载时返回空字符串 ''(不抛错,模板不崩)\n * - level 加载完成后自动重新计算并返回正确 URL\n * - 路由名不存在或必填参数缺失等渲染期错误:降级为 '' 保证渲染不中断,\n * 同时以醒目的样式化 warn 输出完整错误(含堆栈)——开发期可见,生产无副作用\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\n/** 渲染期错误降级输出:橙色加粗标签 + 完整错误对象,控制台一眼可见 */\nfunction warnRenderError(error: unknown): void {\n console.warn(\n '%c[route-forge]%c useForgeRoute 渲染期错误(已降级为空字符串,渲染未中断)',\n 'color:#e67e22;font-weight:bold',\n 'color:inherit',\n error,\n );\n}\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 try {\n return forge.route(l, n, p);\n } catch (e) {\n warnRenderError(e);\n return '';\n }\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeRoute.ts"],"names":["createRouteForge","inject","ref","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 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: true,\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 * pending 采用引用计数:并发多个 call 时,全部完成才置 false\n * (先完成的 call 不再把其他在途请求的 pending 提前清掉)。\n */\n\nimport type { Ref } from 'vue';\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type {\n BoundForge,\n RouteForge,\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 bound = level !== undefined ? useForge(level, prefix as string) : undefined;\n const unbound = bound === undefined ? useForge() : undefined;\n const pending = ref(false);\n const error = ref<unknown>(null);\n // 并发计数:setup 闭包变量(组件实例生命周期存活)\n let inflight = 0;\n\n async function call(...args: unknown[]): Promise<{ data: unknown; error: unknown }> {\n inflight++;\n pending.value = true;\n error.value = null;\n try {\n // 按绑定形态分发:bound 走 BoundForge.api(name, params),unbound 走 RouteForge.api(level, name, params)\n // (窄断言替代 as any:重载签名已保证参数形状,此处仅消除联合类型/框架特化类型的分支歧义)\n const data = bound !== undefined\n ? await (bound as unknown as BoundForge).api(args[0] as string, args[1] as never)\n : await (unbound as RouteForge).api(args[0] as string, args[1] as string, args[2] as never);\n return { data, error: null };\n } catch (e) {\n error.value = e;\n return { data: undefined, error: e };\n } finally {\n inflight--;\n pending.value = inflight > 0;\n }\n }\n\n return { pending, error, call: call as unknown as UseForgeApiCall };\n}\n","/**\n * useForgeRoute:响应式 URL 生成器,内部处理 level 加载状态\n * @see .docs/SPEC.md §4.1.7\n *\n * - level 未加载时返回空字符串 ''(不抛错,模板不崩)\n * - level 加载完成后自动重新计算并返回正确 URL\n * - 路由名不存在或必填参数缺失等渲染期错误:降级为 '' 保证渲染不中断,\n * 同时以醒目的样式化 warn 输出完整错误(含堆栈)——开发期可见,生产无副作用\n * - level 为静态层级绑定:即使在函数形式下也只在 setup 求值一次即固定,不支持中途动态切换 level\n * (需要另一个层级请在别的组件 / 别的 useForgeRoute 调用里分别使用,与 useForge 契约一致)\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\n/** 渲染期错误降级输出:橙色加粗标签 + 完整错误对象,控制台一眼可见 */\nfunction warnRenderError(error: unknown): void {\n console.warn(\n '%c[route-forge]%c useForgeRoute 渲染期错误(已降级为空字符串,渲染未中断)',\n 'color:#e67e22;font-weight:bold',\n 'color:inherit',\n error,\n );\n}\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 静态化:setup 时求值一次即固定,之后不追踪函数形式 getter 的变化\n //(即便调用方传入 `() => string`,也只读取一次)。name / params 仍保持响应式。\n const lvl = typeof level === 'function' ? level() : level;\n\n // 响应式追踪该 level 的加载状态(computed 依赖此 ref 触发重算)\n const levelLoaded = ref(forge.isLoaded(lvl));\n\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 // lvl 为 setup 快照(静态);name / params 每次重算读取,保持响应式\n const n = typeof name === 'function' ? name() : name;\n const p = params ? params() : undefined;\n try {\n return forge.route(lvl, n, p);\n } catch (e) {\n warnRenderError(e);\n return '';\n }\n });\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -88,6 +88,8 @@ declare function useForgeApi<L extends string>(level: L, prefix: string): UseFor
|
|
|
88
88
|
* - level 加载完成后自动重新计算并返回正确 URL
|
|
89
89
|
* - 路由名不存在或必填参数缺失等渲染期错误:降级为 '' 保证渲染不中断,
|
|
90
90
|
* 同时以醒目的样式化 warn 输出完整错误(含堆栈)——开发期可见,生产无副作用
|
|
91
|
+
* - level 为静态层级绑定:即使在函数形式下也只在 setup 求值一次即固定,不支持中途动态切换 level
|
|
92
|
+
* (需要另一个层级请在别的组件 / 别的 useForgeRoute 调用里分别使用,与 useForge 契约一致)
|
|
91
93
|
* - 用户无需关心 levelLoaded 状态,直接用即可
|
|
92
94
|
*/
|
|
93
95
|
|
package/dist/index.d.ts
CHANGED
|
@@ -88,6 +88,8 @@ declare function useForgeApi<L extends string>(level: L, prefix: string): UseFor
|
|
|
88
88
|
* - level 加载完成后自动重新计算并返回正确 URL
|
|
89
89
|
* - 路由名不存在或必填参数缺失等渲染期错误:降级为 '' 保证渲染不中断,
|
|
90
90
|
* 同时以醒目的样式化 warn 输出完整错误(含堆栈)——开发期可见,生产无副作用
|
|
91
|
+
* - level 为静态层级绑定:即使在函数形式下也只在 setup 求值一次即固定,不支持中途动态切换 level
|
|
92
|
+
* (需要另一个层级请在别的组件 / 别的 useForgeRoute 调用里分别使用,与 useForge 契约一致)
|
|
91
93
|
* - 用户无需关心 levelLoaded 状态,直接用即可
|
|
92
94
|
*/
|
|
93
95
|
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ function useForge(level, prefix) {
|
|
|
35
35
|
value: levelLoadedRef,
|
|
36
36
|
writable: false,
|
|
37
37
|
enumerable: true,
|
|
38
|
-
configurable:
|
|
38
|
+
configurable: true
|
|
39
39
|
});
|
|
40
40
|
return bound;
|
|
41
41
|
}
|
|
@@ -72,8 +72,8 @@ function warnRenderError(error) {
|
|
|
72
72
|
}
|
|
73
73
|
function useForgeRoute(level, name, params) {
|
|
74
74
|
const forge = inject(FORGE_INJECTION_KEY);
|
|
75
|
-
const levelLoaded = ref(forge.isLoaded(typeof level === "function" ? level() : level));
|
|
76
75
|
const lvl = typeof level === "function" ? level() : level;
|
|
76
|
+
const levelLoaded = ref(forge.isLoaded(lvl));
|
|
77
77
|
if (!levelLoaded.value) {
|
|
78
78
|
onMounted(() => {
|
|
79
79
|
forge.load(lvl).then(() => {
|
|
@@ -84,11 +84,10 @@ function useForgeRoute(level, name, params) {
|
|
|
84
84
|
}
|
|
85
85
|
return computed(() => {
|
|
86
86
|
if (!levelLoaded.value) return "";
|
|
87
|
-
const l = typeof level === "function" ? level() : level;
|
|
88
87
|
const n = typeof name === "function" ? name() : name;
|
|
89
88
|
const p = params ? params() : void 0;
|
|
90
89
|
try {
|
|
91
|
-
return forge.route(
|
|
90
|
+
return forge.route(lvl, n, p);
|
|
92
91
|
} catch (e) {
|
|
93
92
|
warnRenderError(e);
|
|
94
93
|
return "";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeRoute.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 * pending 采用引用计数:并发多个 call 时,全部完成才置 false\n * (先完成的 call 不再把其他在途请求的 pending 提前清掉)。\n */\n\nimport type { Ref } from 'vue';\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type {\n BoundForge,\n RouteForge,\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 bound = level !== undefined ? useForge(level, prefix as string) : undefined;\n const unbound = bound === undefined ? useForge() : undefined;\n const pending = ref(false);\n const error = ref<unknown>(null);\n // 并发计数:setup 闭包变量(组件实例生命周期存活)\n let inflight = 0;\n\n async function call(...args: unknown[]): Promise<{ data: unknown; error: unknown }> {\n inflight++;\n pending.value = true;\n error.value = null;\n try {\n // 按绑定形态分发:bound 走 BoundForge.api(name, params),unbound 走 RouteForge.api(level, name, params)\n // (窄断言替代 as any:重载签名已保证参数形状,此处仅消除联合类型/框架特化类型的分支歧义)\n const data = bound !== undefined\n ? await (bound as unknown as BoundForge).api(args[0] as string, args[1] as never)\n : await (unbound as RouteForge).api(args[0] as string, args[1] as string, args[2] as never);\n return { data, error: null };\n } catch (e) {\n error.value = e;\n return { data: undefined, error: e };\n } finally {\n inflight--;\n pending.value = inflight > 0;\n }\n }\n\n return { pending, error, call: call as unknown as UseForgeApiCall };\n}\n","/**\n * useForgeRoute:响应式 URL 生成器,内部处理 level 加载状态\n * @see .docs/SPEC.md §4.1.7\n *\n * - level 未加载时返回空字符串 ''(不抛错,模板不崩)\n * - level 加载完成后自动重新计算并返回正确 URL\n * - 路由名不存在或必填参数缺失等渲染期错误:降级为 '' 保证渲染不中断,\n * 同时以醒目的样式化 warn 输出完整错误(含堆栈)——开发期可见,生产无副作用\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\n/** 渲染期错误降级输出:橙色加粗标签 + 完整错误对象,控制台一眼可见 */\nfunction warnRenderError(error: unknown): void {\n console.warn(\n '%c[route-forge]%c useForgeRoute 渲染期错误(已降级为空字符串,渲染未中断)',\n 'color:#e67e22;font-weight:bold',\n 'color:inherit',\n error,\n );\n}\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 try {\n return forge.route(l, n, p);\n } catch (e) {\n warnRenderError(e);\n return '';\n }\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeRoute.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: true,\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 * pending 采用引用计数:并发多个 call 时,全部完成才置 false\n * (先完成的 call 不再把其他在途请求的 pending 提前清掉)。\n */\n\nimport type { Ref } from 'vue';\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type {\n BoundForge,\n RouteForge,\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 bound = level !== undefined ? useForge(level, prefix as string) : undefined;\n const unbound = bound === undefined ? useForge() : undefined;\n const pending = ref(false);\n const error = ref<unknown>(null);\n // 并发计数:setup 闭包变量(组件实例生命周期存活)\n let inflight = 0;\n\n async function call(...args: unknown[]): Promise<{ data: unknown; error: unknown }> {\n inflight++;\n pending.value = true;\n error.value = null;\n try {\n // 按绑定形态分发:bound 走 BoundForge.api(name, params),unbound 走 RouteForge.api(level, name, params)\n // (窄断言替代 as any:重载签名已保证参数形状,此处仅消除联合类型/框架特化类型的分支歧义)\n const data = bound !== undefined\n ? await (bound as unknown as BoundForge).api(args[0] as string, args[1] as never)\n : await (unbound as RouteForge).api(args[0] as string, args[1] as string, args[2] as never);\n return { data, error: null };\n } catch (e) {\n error.value = e;\n return { data: undefined, error: e };\n } finally {\n inflight--;\n pending.value = inflight > 0;\n }\n }\n\n return { pending, error, call: call as unknown as UseForgeApiCall };\n}\n","/**\n * useForgeRoute:响应式 URL 生成器,内部处理 level 加载状态\n * @see .docs/SPEC.md §4.1.7\n *\n * - level 未加载时返回空字符串 ''(不抛错,模板不崩)\n * - level 加载完成后自动重新计算并返回正确 URL\n * - 路由名不存在或必填参数缺失等渲染期错误:降级为 '' 保证渲染不中断,\n * 同时以醒目的样式化 warn 输出完整错误(含堆栈)——开发期可见,生产无副作用\n * - level 为静态层级绑定:即使在函数形式下也只在 setup 求值一次即固定,不支持中途动态切换 level\n * (需要另一个层级请在别的组件 / 别的 useForgeRoute 调用里分别使用,与 useForge 契约一致)\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\n/** 渲染期错误降级输出:橙色加粗标签 + 完整错误对象,控制台一眼可见 */\nfunction warnRenderError(error: unknown): void {\n console.warn(\n '%c[route-forge]%c useForgeRoute 渲染期错误(已降级为空字符串,渲染未中断)',\n 'color:#e67e22;font-weight:bold',\n 'color:inherit',\n error,\n );\n}\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 静态化:setup 时求值一次即固定,之后不追踪函数形式 getter 的变化\n //(即便调用方传入 `() => string`,也只读取一次)。name / params 仍保持响应式。\n const lvl = typeof level === 'function' ? level() : level;\n\n // 响应式追踪该 level 的加载状态(computed 依赖此 ref 触发重算)\n const levelLoaded = ref(forge.isLoaded(lvl));\n\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 // lvl 为 setup 快照(静态);name / params 每次重算读取,保持响应式\n const n = typeof name === 'function' ? name() : name;\n const p = params ? params() : undefined;\n try {\n return forge.route(lvl, n, p);\n } catch (e) {\n warnRenderError(e);\n return '';\n }\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@route-forge/vue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Route Forge 的 Vue 3 集成:插件 + composable(useForge/useForgeApi/useForgeRoute)",
|
|
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": "^2.
|
|
43
|
+
"@route-forge/core": "^2.1.0"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|