@route-forge/vue 0.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/LICENSE +21 -0
- package/README.md +42 -0
- package/dist/index.cjs +88 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +69 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 阿杰很厉害
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# @route-forge/vue
|
|
2
|
+
|
|
3
|
+
Route Forge 的 Vue 3 集成:插件 + composable(`useForgeApi` / `useForgeLevel` / `useForgeRoute` / `useForgeByPrefix`)。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @route-forge/vue @route-forge/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 基本用法
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// main.ts
|
|
15
|
+
import { createApp } from 'vue'
|
|
16
|
+
import { ForgePlugin } from '@route-forge/vue'
|
|
17
|
+
import App from './App.vue'
|
|
18
|
+
|
|
19
|
+
const app = createApp(App)
|
|
20
|
+
app.use(ForgePlugin, {
|
|
21
|
+
endpoint: '/_forge/routes',
|
|
22
|
+
})
|
|
23
|
+
app.mount('#app')
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { useForgeRoute } from '@route-forge/vue'
|
|
29
|
+
|
|
30
|
+
const { data: route } = useForgeRoute('login.show')
|
|
31
|
+
</script>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 文档
|
|
35
|
+
|
|
36
|
+
- 仓库主页: https://github.com/xyj2156/route-forge
|
|
37
|
+
- 设计文档: https://github.com/xyj2156/route-forge/blob/main/.docs/DESIGN.md
|
|
38
|
+
- 规范: https://github.com/xyj2156/route-forge/blob/main/.docs/SPEC.md
|
|
39
|
+
|
|
40
|
+
## License
|
|
41
|
+
|
|
42
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var vue = require('vue');
|
|
4
|
+
var core = require('@route-forge/core');
|
|
5
|
+
|
|
6
|
+
// src/plugin.ts
|
|
7
|
+
var FORGE_INJECTION_KEY = /* @__PURE__ */ Symbol("route-forge");
|
|
8
|
+
function createRouteForgePlugin(options) {
|
|
9
|
+
const forge = core.createRouteForge(options);
|
|
10
|
+
return {
|
|
11
|
+
install(app) {
|
|
12
|
+
app.provide(FORGE_INJECTION_KEY, forge);
|
|
13
|
+
app.config.globalProperties.$forge = {
|
|
14
|
+
route: (name, params) => forge.route(name, params)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function useForge() {
|
|
20
|
+
const forge = vue.inject(FORGE_INJECTION_KEY);
|
|
21
|
+
if (!forge) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
"[route-forge/vue] useForge() must be used inside an app with createRouteForgePlugin() installed"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return forge;
|
|
27
|
+
}
|
|
28
|
+
function useForgeApi() {
|
|
29
|
+
const forge = useForge();
|
|
30
|
+
const pending = vue.ref(false);
|
|
31
|
+
const error = vue.ref(null);
|
|
32
|
+
async function call(name, params) {
|
|
33
|
+
pending.value = true;
|
|
34
|
+
error.value = null;
|
|
35
|
+
try {
|
|
36
|
+
const data = await forge.api(name, params);
|
|
37
|
+
return { data, error: null };
|
|
38
|
+
} catch (e) {
|
|
39
|
+
error.value = e;
|
|
40
|
+
return { data: void 0, error: e };
|
|
41
|
+
} finally {
|
|
42
|
+
pending.value = false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { pending, error, call };
|
|
46
|
+
}
|
|
47
|
+
function useForgeLevel(level) {
|
|
48
|
+
const forge = useForge();
|
|
49
|
+
const loaded = vue.ref(false);
|
|
50
|
+
const error = vue.ref(null);
|
|
51
|
+
vue.onMounted(async () => {
|
|
52
|
+
try {
|
|
53
|
+
await forge.load(level);
|
|
54
|
+
loaded.value = true;
|
|
55
|
+
} catch (e) {
|
|
56
|
+
error.value = e;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return { loaded, error };
|
|
60
|
+
}
|
|
61
|
+
function useForgeRoute(name, params) {
|
|
62
|
+
const forge = useForge();
|
|
63
|
+
return vue.computed(() => {
|
|
64
|
+
const n = typeof name === "function" ? name() : name;
|
|
65
|
+
const p = params ? params() : void 0;
|
|
66
|
+
return forge.route(n, p);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/composables/useForgeByPrefix.ts
|
|
71
|
+
function useForgeByPrefix(prefix, separator = ".") {
|
|
72
|
+
const forge = useForge();
|
|
73
|
+
const join = (suffix) => suffix ? `${prefix}${separator}${suffix}` : prefix;
|
|
74
|
+
return {
|
|
75
|
+
api: (suffix, params) => forge.api(join(suffix), params),
|
|
76
|
+
route: (suffix, params) => forge.route(join(suffix), params)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
exports.FORGE_INJECTION_KEY = FORGE_INJECTION_KEY;
|
|
81
|
+
exports.createRouteForgePlugin = createRouteForgePlugin;
|
|
82
|
+
exports.useForge = useForge;
|
|
83
|
+
exports.useForgeApi = useForgeApi;
|
|
84
|
+
exports.useForgeByPrefix = useForgeByPrefix;
|
|
85
|
+
exports.useForgeLevel = useForgeLevel;
|
|
86
|
+
exports.useForgeRoute = useForgeRoute;
|
|
87
|
+
//# sourceMappingURL=index.cjs.map
|
|
88
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeLevel.ts","../src/composables/useForgeRoute.ts","../src/composables/useForgeByPrefix.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 */\n\nimport type { App, InjectionKey } from 'vue';\nimport { inject, reactive, readonly } from 'vue';\nimport {\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\nexport function createRouteForgePlugin(options: RouteForgePluginOptions) {\n const forge = createRouteForge(options);\n\n return {\n install(app: App) {\n app.provide(FORGE_INJECTION_KEY, forge);\n app.config.globalProperties.$forge = {\n route: (name: string, params?: Record<string, unknown>) =>\n forge.route(name, params),\n };\n },\n };\n}\n\nexport function useForge(): RouteForge {\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 return forge;\n}\n\nexport { readonly, reactive };\n","/**\n * useForgeApi:包装 forge.api(),自动管理 loading/error 状态\n * @see .docs/SPEC.md §4.1.7\n */\n\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type { ApiCallParams } from '@route-forge/core';\n\nexport interface UseForgeApiReturn {\n pending: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<unknown>>;\n call: (name: string, params?: ApiCallParams) => Promise<{\n data: unknown;\n error: unknown;\n }>;\n}\n\nexport function useForgeApi(): UseForgeApiReturn {\n const forge = useForge();\n const pending = ref(false);\n const error = ref<unknown>(null);\n\n async function call(name: string, params?: ApiCallParams) {\n pending.value = true;\n error.value = null;\n try {\n const data = await forge.api(name, params);\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 };\n}\n","/**\n * useForgeLevel:声明组件依赖某层级,挂载时自动 forge.load(level),销毁时不主动失效\n * @see .docs/SPEC.md §4.1.7\n */\n\nimport { onMounted, ref } from 'vue';\nimport { useForge } from '../plugin.js';\n\nexport interface UseForgeLevelReturn {\n loaded: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<unknown>>;\n}\n\nexport function useForgeLevel(level: string): UseForgeLevelReturn {\n const forge = useForge();\n const loaded = ref(false);\n const error = ref<unknown>(null);\n\n onMounted(async () => {\n try {\n await forge.load(level);\n loaded.value = true;\n } catch (e) {\n error.value = e;\n }\n });\n\n return { loaded, error };\n}\n","/**\n * useForgeRoute:仅生成 URL,不发请求(用于 <a href>、外部跳转等)\n * @see .docs/SPEC.md §4.1.7\n */\n\nimport { computed, type ComputedRef } from 'vue';\nimport { useForge } from '../plugin.js';\n\nexport function useForgeRoute(\n name: string | (() => string),\n params?: () => Record<string, unknown>,\n): ComputedRef<string> {\n const forge = useForge();\n return computed(() => {\n const n = typeof name === 'function' ? name() : name;\n const p = params ? params() : undefined;\n return forge.route(n, p);\n });\n}\n","/**\n * useForgeByPrefix:带名字前缀的封装,方便后续减少名称传入\n * @see .docs/SPEC.md §4.1.7\n *\n * 示例:\n * const { api } = useForgeByPrefix('admin.users');\n * await api('show', { user: 1 }); // 等价于 forge.api('admin.users.show', { user: 1 })\n */\n\nimport { useForge } from '../plugin.js';\nimport type { ApiCallParams } from '@route-forge/core';\n\nexport interface UseForgeByPrefixReturn {\n api: (suffix: string, params?: ApiCallParams) => Promise<unknown>;\n route: (suffix: string, params?: Record<string, unknown>) => string;\n}\n\nexport function useForgeByPrefix(prefix: string, separator = '.'): UseForgeByPrefixReturn {\n const forge = useForge();\n\n const join = (suffix: string) => (suffix ? `${prefix}${separator}${suffix}` : prefix);\n\n return {\n api: (suffix, params) => forge.api(join(suffix), params),\n route: (suffix, params) => forge.route(join(suffix), params),\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { InjectionKey, App, ref, ComputedRef } from 'vue';
|
|
2
|
+
import { RouteForge, RouteForgeOptions, ApiCallParams } from '@route-forge/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Vue 3 插件入口
|
|
6
|
+
* @see .docs/SPEC.md §4.1.7
|
|
7
|
+
*
|
|
8
|
+
* 提供:
|
|
9
|
+
* - 全局属性 $forge(route() 工具)
|
|
10
|
+
* - inject symbol 注入 RouteForge 实例供 composable 使用
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
declare const FORGE_INJECTION_KEY: InjectionKey<RouteForge>;
|
|
14
|
+
interface RouteForgePluginOptions extends RouteForgeOptions {
|
|
15
|
+
}
|
|
16
|
+
declare function createRouteForgePlugin(options: RouteForgePluginOptions): {
|
|
17
|
+
install(app: App): void;
|
|
18
|
+
};
|
|
19
|
+
declare function useForge(): RouteForge;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* useForgeApi:包装 forge.api(),自动管理 loading/error 状态
|
|
23
|
+
* @see .docs/SPEC.md §4.1.7
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
interface UseForgeApiReturn {
|
|
27
|
+
pending: ReturnType<typeof ref<boolean>>;
|
|
28
|
+
error: ReturnType<typeof ref<unknown>>;
|
|
29
|
+
call: (name: string, params?: ApiCallParams) => Promise<{
|
|
30
|
+
data: unknown;
|
|
31
|
+
error: unknown;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
declare function useForgeApi(): UseForgeApiReturn;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* useForgeLevel:声明组件依赖某层级,挂载时自动 forge.load(level),销毁时不主动失效
|
|
38
|
+
* @see .docs/SPEC.md §4.1.7
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
interface UseForgeLevelReturn {
|
|
42
|
+
loaded: ReturnType<typeof ref<boolean>>;
|
|
43
|
+
error: ReturnType<typeof ref<unknown>>;
|
|
44
|
+
}
|
|
45
|
+
declare function useForgeLevel(level: string): UseForgeLevelReturn;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* useForgeRoute:仅生成 URL,不发请求(用于 <a href>、外部跳转等)
|
|
49
|
+
* @see .docs/SPEC.md §4.1.7
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
declare function useForgeRoute(name: string | (() => string), params?: () => Record<string, unknown>): ComputedRef<string>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* useForgeByPrefix:带名字前缀的封装,方便后续减少名称传入
|
|
56
|
+
* @see .docs/SPEC.md §4.1.7
|
|
57
|
+
*
|
|
58
|
+
* 示例:
|
|
59
|
+
* const { api } = useForgeByPrefix('admin.users');
|
|
60
|
+
* await api('show', { user: 1 }); // 等价于 forge.api('admin.users.show', { user: 1 })
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
interface UseForgeByPrefixReturn {
|
|
64
|
+
api: (suffix: string, params?: ApiCallParams) => Promise<unknown>;
|
|
65
|
+
route: (suffix: string, params?: Record<string, unknown>) => string;
|
|
66
|
+
}
|
|
67
|
+
declare function useForgeByPrefix(prefix: string, separator?: string): UseForgeByPrefixReturn;
|
|
68
|
+
|
|
69
|
+
export { FORGE_INJECTION_KEY, type RouteForgePluginOptions, type UseForgeApiReturn, type UseForgeByPrefixReturn, type UseForgeLevelReturn, createRouteForgePlugin, useForge, useForgeApi, useForgeByPrefix, useForgeLevel, useForgeRoute };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { InjectionKey, App, ref, ComputedRef } from 'vue';
|
|
2
|
+
import { RouteForge, RouteForgeOptions, ApiCallParams } from '@route-forge/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Vue 3 插件入口
|
|
6
|
+
* @see .docs/SPEC.md §4.1.7
|
|
7
|
+
*
|
|
8
|
+
* 提供:
|
|
9
|
+
* - 全局属性 $forge(route() 工具)
|
|
10
|
+
* - inject symbol 注入 RouteForge 实例供 composable 使用
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
declare const FORGE_INJECTION_KEY: InjectionKey<RouteForge>;
|
|
14
|
+
interface RouteForgePluginOptions extends RouteForgeOptions {
|
|
15
|
+
}
|
|
16
|
+
declare function createRouteForgePlugin(options: RouteForgePluginOptions): {
|
|
17
|
+
install(app: App): void;
|
|
18
|
+
};
|
|
19
|
+
declare function useForge(): RouteForge;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* useForgeApi:包装 forge.api(),自动管理 loading/error 状态
|
|
23
|
+
* @see .docs/SPEC.md §4.1.7
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
interface UseForgeApiReturn {
|
|
27
|
+
pending: ReturnType<typeof ref<boolean>>;
|
|
28
|
+
error: ReturnType<typeof ref<unknown>>;
|
|
29
|
+
call: (name: string, params?: ApiCallParams) => Promise<{
|
|
30
|
+
data: unknown;
|
|
31
|
+
error: unknown;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
declare function useForgeApi(): UseForgeApiReturn;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* useForgeLevel:声明组件依赖某层级,挂载时自动 forge.load(level),销毁时不主动失效
|
|
38
|
+
* @see .docs/SPEC.md §4.1.7
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
interface UseForgeLevelReturn {
|
|
42
|
+
loaded: ReturnType<typeof ref<boolean>>;
|
|
43
|
+
error: ReturnType<typeof ref<unknown>>;
|
|
44
|
+
}
|
|
45
|
+
declare function useForgeLevel(level: string): UseForgeLevelReturn;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* useForgeRoute:仅生成 URL,不发请求(用于 <a href>、外部跳转等)
|
|
49
|
+
* @see .docs/SPEC.md §4.1.7
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
declare function useForgeRoute(name: string | (() => string), params?: () => Record<string, unknown>): ComputedRef<string>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* useForgeByPrefix:带名字前缀的封装,方便后续减少名称传入
|
|
56
|
+
* @see .docs/SPEC.md §4.1.7
|
|
57
|
+
*
|
|
58
|
+
* 示例:
|
|
59
|
+
* const { api } = useForgeByPrefix('admin.users');
|
|
60
|
+
* await api('show', { user: 1 }); // 等价于 forge.api('admin.users.show', { user: 1 })
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
interface UseForgeByPrefixReturn {
|
|
64
|
+
api: (suffix: string, params?: ApiCallParams) => Promise<unknown>;
|
|
65
|
+
route: (suffix: string, params?: Record<string, unknown>) => string;
|
|
66
|
+
}
|
|
67
|
+
declare function useForgeByPrefix(prefix: string, separator?: string): UseForgeByPrefixReturn;
|
|
68
|
+
|
|
69
|
+
export { FORGE_INJECTION_KEY, type RouteForgePluginOptions, type UseForgeApiReturn, type UseForgeByPrefixReturn, type UseForgeLevelReturn, createRouteForgePlugin, useForge, useForgeApi, useForgeByPrefix, useForgeLevel, useForgeRoute };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { inject, ref, onMounted, computed } from 'vue';
|
|
2
|
+
import { createRouteForge } from '@route-forge/core';
|
|
3
|
+
|
|
4
|
+
// src/plugin.ts
|
|
5
|
+
var FORGE_INJECTION_KEY = /* @__PURE__ */ Symbol("route-forge");
|
|
6
|
+
function createRouteForgePlugin(options) {
|
|
7
|
+
const forge = createRouteForge(options);
|
|
8
|
+
return {
|
|
9
|
+
install(app) {
|
|
10
|
+
app.provide(FORGE_INJECTION_KEY, forge);
|
|
11
|
+
app.config.globalProperties.$forge = {
|
|
12
|
+
route: (name, params) => forge.route(name, params)
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function useForge() {
|
|
18
|
+
const forge = inject(FORGE_INJECTION_KEY);
|
|
19
|
+
if (!forge) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
"[route-forge/vue] useForge() must be used inside an app with createRouteForgePlugin() installed"
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
return forge;
|
|
25
|
+
}
|
|
26
|
+
function useForgeApi() {
|
|
27
|
+
const forge = useForge();
|
|
28
|
+
const pending = ref(false);
|
|
29
|
+
const error = ref(null);
|
|
30
|
+
async function call(name, params) {
|
|
31
|
+
pending.value = true;
|
|
32
|
+
error.value = null;
|
|
33
|
+
try {
|
|
34
|
+
const data = await forge.api(name, params);
|
|
35
|
+
return { data, error: null };
|
|
36
|
+
} catch (e) {
|
|
37
|
+
error.value = e;
|
|
38
|
+
return { data: void 0, error: e };
|
|
39
|
+
} finally {
|
|
40
|
+
pending.value = false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { pending, error, call };
|
|
44
|
+
}
|
|
45
|
+
function useForgeLevel(level) {
|
|
46
|
+
const forge = useForge();
|
|
47
|
+
const loaded = ref(false);
|
|
48
|
+
const error = ref(null);
|
|
49
|
+
onMounted(async () => {
|
|
50
|
+
try {
|
|
51
|
+
await forge.load(level);
|
|
52
|
+
loaded.value = true;
|
|
53
|
+
} catch (e) {
|
|
54
|
+
error.value = e;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return { loaded, error };
|
|
58
|
+
}
|
|
59
|
+
function useForgeRoute(name, params) {
|
|
60
|
+
const forge = useForge();
|
|
61
|
+
return computed(() => {
|
|
62
|
+
const n = typeof name === "function" ? name() : name;
|
|
63
|
+
const p = params ? params() : void 0;
|
|
64
|
+
return forge.route(n, p);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/composables/useForgeByPrefix.ts
|
|
69
|
+
function useForgeByPrefix(prefix, separator = ".") {
|
|
70
|
+
const forge = useForge();
|
|
71
|
+
const join = (suffix) => suffix ? `${prefix}${separator}${suffix}` : prefix;
|
|
72
|
+
return {
|
|
73
|
+
api: (suffix, params) => forge.api(join(suffix), params),
|
|
74
|
+
route: (suffix, params) => forge.route(join(suffix), params)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { FORGE_INJECTION_KEY, createRouteForgePlugin, useForge, useForgeApi, useForgeByPrefix, useForgeLevel, useForgeRoute };
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/composables/useForgeApi.ts","../src/composables/useForgeLevel.ts","../src/composables/useForgeRoute.ts","../src/composables/useForgeByPrefix.ts"],"names":["ref"],"mappings":";;;;AAiBO,IAAM,mBAAA,0BAAuD,aAAa;AAI1E,SAAS,uBAAuB,OAAA,EAAkC;AACvE,EAAA,MAAM,KAAA,GAAQ,iBAAiB,OAAO,CAAA;AAEtC,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,EAAU;AAChB,MAAA,GAAA,CAAI,OAAA,CAAQ,qBAAqB,KAAK,CAAA;AACtC,MAAA,GAAA,CAAI,MAAA,CAAO,iBAAiB,MAAA,GAAS;AAAA,QACnC,OAAO,CAAC,IAAA,EAAc,WACpB,KAAA,CAAM,KAAA,CAAM,MAAM,MAAM;AAAA,OAC5B;AAAA,IACF;AAAA,GACF;AACF;AAEO,SAAS,QAAA,GAAuB;AACrC,EAAA,MAAM,KAAA,GAAQ,OAAO,mBAAmB,CAAA;AACxC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;ACzBO,SAAS,WAAA,GAAiC;AAC/C,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,OAAA,GAAU,IAAI,KAAK,CAAA;AACzB,EAAA,MAAM,KAAA,GAAQ,IAAa,IAAI,CAAA;AAE/B,EAAA,eAAe,IAAA,CAAK,MAAc,MAAA,EAAwB;AACxD,IAAA,OAAA,CAAQ,KAAA,GAAQ,IAAA;AAChB,IAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AACd,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,CAAM,GAAA,CAAI,MAAM,MAAM,CAAA;AACzC,MAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK;AAAA,IAC7B,SAAS,CAAA,EAAG;AACV,MAAA,KAAA,CAAM,KAAA,GAAQ,CAAA;AACd,MAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAW,KAAA,EAAO,CAAA,EAAE;AAAA,IACrC,CAAA,SAAE;AACA,MAAA,OAAA,CAAQ,KAAA,GAAQ,KAAA;AAAA,IAClB;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,IAAA,EAAK;AAChC;ACzBO,SAAS,cAAc,KAAA,EAAoC;AAChE,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,MAAA,GAASA,IAAI,KAAK,CAAA;AACxB,EAAA,MAAM,KAAA,GAAQA,IAAa,IAAI,CAAA;AAE/B,EAAA,SAAA,CAAU,YAAY;AACpB,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,CAAM,KAAK,KAAK,CAAA;AACtB,MAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AAAA,IACjB,SAAS,CAAA,EAAG;AACV,MAAA,KAAA,CAAM,KAAA,GAAQ,CAAA;AAAA,IAChB;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,EAAE,QAAQ,KAAA,EAAM;AACzB;ACpBO,SAAS,aAAA,CACd,MACA,MAAA,EACqB;AACrB,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,OAAO,SAAS,MAAM;AACpB,IAAA,MAAM,CAAA,GAAI,OAAO,IAAA,KAAS,UAAA,GAAa,MAAK,GAAI,IAAA;AAChD,IAAA,MAAM,CAAA,GAAI,MAAA,GAAS,MAAA,EAAO,GAAI,MAAA;AAC9B,IAAA,OAAO,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAAA,EACzB,CAAC,CAAA;AACH;;;ACDO,SAAS,gBAAA,CAAiB,MAAA,EAAgB,SAAA,GAAY,GAAA,EAA6B;AACxF,EAAA,MAAM,QAAQ,QAAA,EAAS;AAEvB,EAAA,MAAM,IAAA,GAAO,CAAC,MAAA,KAAoB,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,EAAG,SAAS,CAAA,EAAG,MAAM,CAAA,CAAA,GAAK,MAAA;AAE9E,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,CAAC,MAAA,EAAQ,MAAA,KAAW,MAAM,GAAA,CAAI,IAAA,CAAK,MAAM,CAAA,EAAG,MAAM,CAAA;AAAA,IACvD,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,KAAW,MAAM,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,EAAG,MAAM;AAAA,GAC7D;AACF","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 */\n\nimport type { App, InjectionKey } from 'vue';\nimport { inject, reactive, readonly } from 'vue';\nimport {\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\nexport function createRouteForgePlugin(options: RouteForgePluginOptions) {\n const forge = createRouteForge(options);\n\n return {\n install(app: App) {\n app.provide(FORGE_INJECTION_KEY, forge);\n app.config.globalProperties.$forge = {\n route: (name: string, params?: Record<string, unknown>) =>\n forge.route(name, params),\n };\n },\n };\n}\n\nexport function useForge(): RouteForge {\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 return forge;\n}\n\nexport { readonly, reactive };\n","/**\n * useForgeApi:包装 forge.api(),自动管理 loading/error 状态\n * @see .docs/SPEC.md §4.1.7\n */\n\nimport { ref } from 'vue';\nimport { useForge } from '../plugin.js';\nimport type { ApiCallParams } from '@route-forge/core';\n\nexport interface UseForgeApiReturn {\n pending: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<unknown>>;\n call: (name: string, params?: ApiCallParams) => Promise<{\n data: unknown;\n error: unknown;\n }>;\n}\n\nexport function useForgeApi(): UseForgeApiReturn {\n const forge = useForge();\n const pending = ref(false);\n const error = ref<unknown>(null);\n\n async function call(name: string, params?: ApiCallParams) {\n pending.value = true;\n error.value = null;\n try {\n const data = await forge.api(name, params);\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 };\n}\n","/**\n * useForgeLevel:声明组件依赖某层级,挂载时自动 forge.load(level),销毁时不主动失效\n * @see .docs/SPEC.md §4.1.7\n */\n\nimport { onMounted, ref } from 'vue';\nimport { useForge } from '../plugin.js';\n\nexport interface UseForgeLevelReturn {\n loaded: ReturnType<typeof ref<boolean>>;\n error: ReturnType<typeof ref<unknown>>;\n}\n\nexport function useForgeLevel(level: string): UseForgeLevelReturn {\n const forge = useForge();\n const loaded = ref(false);\n const error = ref<unknown>(null);\n\n onMounted(async () => {\n try {\n await forge.load(level);\n loaded.value = true;\n } catch (e) {\n error.value = e;\n }\n });\n\n return { loaded, error };\n}\n","/**\n * useForgeRoute:仅生成 URL,不发请求(用于 <a href>、外部跳转等)\n * @see .docs/SPEC.md §4.1.7\n */\n\nimport { computed, type ComputedRef } from 'vue';\nimport { useForge } from '../plugin.js';\n\nexport function useForgeRoute(\n name: string | (() => string),\n params?: () => Record<string, unknown>,\n): ComputedRef<string> {\n const forge = useForge();\n return computed(() => {\n const n = typeof name === 'function' ? name() : name;\n const p = params ? params() : undefined;\n return forge.route(n, p);\n });\n}\n","/**\n * useForgeByPrefix:带名字前缀的封装,方便后续减少名称传入\n * @see .docs/SPEC.md §4.1.7\n *\n * 示例:\n * const { api } = useForgeByPrefix('admin.users');\n * await api('show', { user: 1 }); // 等价于 forge.api('admin.users.show', { user: 1 })\n */\n\nimport { useForge } from '../plugin.js';\nimport type { ApiCallParams } from '@route-forge/core';\n\nexport interface UseForgeByPrefixReturn {\n api: (suffix: string, params?: ApiCallParams) => Promise<unknown>;\n route: (suffix: string, params?: Record<string, unknown>) => string;\n}\n\nexport function useForgeByPrefix(prefix: string, separator = '.'): UseForgeByPrefixReturn {\n const forge = useForge();\n\n const join = (suffix: string) => (suffix ? `${prefix}${separator}${suffix}` : prefix);\n\n return {\n api: (suffix, params) => forge.api(join(suffix), params),\n route: (suffix, params) => forge.route(join(suffix), params),\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@route-forge/vue",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Route Forge 的 Vue 3 集成:插件 + composable(useForgeApi/useForgeLevel/useForgeRoute/useForgeByPrefix)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "阿杰很厉害 <506907958@qq.com>",
|
|
7
|
+
"homepage": "https://github.com/xyj2156/route-forge",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/xyj2156/route-forge.git",
|
|
11
|
+
"directory": "packages/vue"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/xyj2156/route-forge/issues"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"main": "./dist/index.cjs",
|
|
19
|
+
"module": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"require": "./dist/index.cjs"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"vue": "^3.3.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@vue/test-utils": "^2.4.0",
|
|
37
|
+
"jsdom": "^24.0.0",
|
|
38
|
+
"tsup": "^8.0.0",
|
|
39
|
+
"vitest": "^1.4.0",
|
|
40
|
+
"vue": "^3.4.0"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@route-forge/core": "0.1.0"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsup",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"test:watch": "vitest",
|
|
52
|
+
"lint": "tsc --noEmit",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"clean": "rimraf dist .turbo"
|
|
55
|
+
}
|
|
56
|
+
}
|