@movk/nuxt 1.1.2 → 1.2.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 +5 -29
- package/dist/module.d.mts +3 -1
- package/dist/module.json +3 -3
- package/dist/module.mjs +120 -34
- package/dist/runtime/auto-form/controls.d.ts +221 -0
- package/dist/runtime/auto-form/controls.js +70 -0
- package/dist/runtime/{utils → auto-form}/field-utils.d.ts +4 -20
- package/dist/runtime/{utils → auto-form}/field-utils.js +1 -2
- package/dist/runtime/auto-form/metadata.d.ts +22 -0
- package/dist/runtime/auto-form/metadata.js +53 -0
- package/dist/runtime/auto-form/provider.d.ts +27 -0
- package/dist/runtime/{internal/useAutoFormProvider.js → auto-form/provider.js} +1 -1
- package/dist/runtime/{utils → auto-form}/reactive-utils.d.ts +4 -22
- package/dist/runtime/{utils → auto-form}/schema-introspector.d.ts +3 -9
- package/dist/runtime/{utils → auto-form}/schema-introspector.js +11 -9
- package/dist/runtime/components/AutoForm.d.vue.ts +4 -5
- package/dist/runtime/components/AutoForm.vue +12 -35
- package/dist/runtime/components/AutoForm.vue.d.ts +4 -5
- package/dist/runtime/components/ColorChooser.d.vue.ts +10 -6
- package/dist/runtime/components/ColorChooser.vue +4 -7
- package/dist/runtime/components/ColorChooser.vue.d.ts +10 -6
- package/dist/runtime/components/DatePicker.d.vue.ts +16 -10
- package/dist/runtime/components/DatePicker.vue.d.ts +16 -10
- package/dist/runtime/components/SearchForm.d.vue.ts +171 -0
- package/dist/runtime/components/SearchForm.vue +216 -0
- package/dist/runtime/components/SearchForm.vue.d.ts +171 -0
- package/dist/runtime/components/SlideVerify.d.vue.ts +5 -32
- package/dist/runtime/components/SlideVerify.vue +4 -4
- package/dist/runtime/components/SlideVerify.vue.d.ts +5 -32
- package/dist/runtime/components/StarRating.d.vue.ts +8 -16
- package/dist/runtime/components/StarRating.vue +50 -65
- package/dist/runtime/components/StarRating.vue.d.ts +8 -16
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.d.vue.ts +10 -2
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.vue +16 -23
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.vue.d.ts +10 -2
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererChildren.d.vue.ts +26 -0
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererChildren.vue +50 -0
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererChildren.vue.d.ts +26 -0
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.d.vue.ts +8 -2
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.vue +2 -2
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.vue.d.ts +8 -2
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.d.vue.ts +8 -2
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.vue +29 -64
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.vue.d.ts +8 -2
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.d.vue.ts +8 -2
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.vue +15 -69
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.vue.d.ts +8 -2
- package/dist/runtime/components/input/AsPhoneNumberInput.d.vue.ts +36 -0
- package/dist/runtime/components/input/AsPhoneNumberInput.vue +35 -0
- package/dist/runtime/components/input/AsPhoneNumberInput.vue.d.ts +36 -0
- package/dist/runtime/components/input/WithCharacterLimit.d.vue.ts +17 -9
- package/dist/runtime/components/input/WithCharacterLimit.vue +5 -5
- package/dist/runtime/components/input/WithCharacterLimit.vue.d.ts +17 -9
- package/dist/runtime/components/input/WithClear.d.vue.ts +13 -9
- package/dist/runtime/components/input/WithClear.vue +2 -2
- package/dist/runtime/components/input/WithClear.vue.d.ts +13 -9
- package/dist/runtime/components/input/WithCopy.d.vue.ts +16 -10
- package/dist/runtime/components/input/WithCopy.vue +3 -3
- package/dist/runtime/components/input/WithCopy.vue.d.ts +16 -10
- package/dist/runtime/components/input/WithFloatingLabel.d.vue.ts +36 -0
- package/dist/runtime/components/input/WithFloatingLabel.vue +67 -0
- package/dist/runtime/components/input/WithFloatingLabel.vue.d.ts +36 -0
- package/dist/runtime/components/input/WithPasswordToggle.d.vue.ts +11 -9
- package/dist/runtime/components/input/WithPasswordToggle.vue +3 -3
- package/dist/runtime/components/input/WithPasswordToggle.vue.d.ts +11 -9
- package/dist/runtime/components/theme-picker/ThemePicker.d.vue.ts +1 -1
- package/dist/runtime/components/theme-picker/ThemePicker.vue +19 -25
- package/dist/runtime/components/theme-picker/ThemePicker.vue.d.ts +1 -1
- package/dist/runtime/components/theme-picker/ThemePickerButton.d.vue.ts +1 -7
- package/dist/runtime/components/theme-picker/ThemePickerButton.vue.d.ts +1 -7
- package/dist/runtime/composables/index.d.ts +1 -1
- package/dist/runtime/composables/index.js +1 -1
- package/dist/runtime/composables/useApiFetch.d.ts +17 -14
- package/dist/runtime/composables/useApiFetch.js +3 -28
- package/dist/runtime/composables/useAutoForm.d.ts +14 -98
- package/dist/runtime/composables/useAutoForm.js +37 -157
- package/dist/runtime/composables/useClientApiFetch.d.ts +5 -6
- package/dist/runtime/composables/useDownloadWithProgress.js +5 -6
- package/dist/runtime/composables/useLazyApiFetch.d.ts +18 -0
- package/dist/runtime/composables/useLazyApiFetch.js +4 -0
- package/dist/runtime/composables/useTheme.d.ts +17 -14
- package/dist/runtime/composables/useTheme.js +68 -72
- package/dist/runtime/composables/useUploadWithProgress.d.ts +2 -2
- package/dist/runtime/composables/useUploadWithProgress.js +7 -7
- package/dist/runtime/constants/api-defaults.d.ts +9 -0
- package/dist/runtime/constants/api-defaults.js +32 -0
- package/dist/runtime/constants/auto-form.d.ts +0 -2
- package/dist/runtime/constants/auto-form.js +0 -25
- package/dist/runtime/constants/grid-cols.d.ts +7 -0
- package/dist/runtime/constants/grid-cols.js +44 -0
- package/dist/runtime/plugins/api.factory.js +78 -121
- package/dist/runtime/plugins/theme.js +44 -64
- package/dist/runtime/style.css +1 -1
- package/dist/runtime/types/api.d.ts +277 -146
- package/dist/runtime/types/auto-form.d.ts +122 -411
- package/dist/runtime/types/index.d.ts +2 -2
- package/dist/runtime/types/index.js +2 -2
- package/dist/runtime/types/module.d.ts +70 -13
- package/dist/runtime/types/theme.d.ts +2 -0
- package/dist/runtime/types/zod.d.ts +11 -10
- package/dist/runtime/utils/api-utils.d.ts +27 -48
- package/dist/runtime/utils/api-utils.js +18 -47
- package/dist/runtime/utils/meta.d.ts +7 -0
- package/dist/runtime/utils/meta.js +16 -0
- package/package.json +36 -35
- package/dist/runtime/composables/useApiAuth.d.ts +0 -47
- package/dist/runtime/composables/useApiAuth.js +0 -66
- package/dist/runtime/internal/useAutoFormProvider.d.ts +0 -50
- package/dist/runtime/schemas/api.d.ts +0 -590
- package/dist/runtime/schemas/api.js +0 -228
- package/dist/runtime/server/api/_movk/session.post.d.ts +0 -10
- package/dist/runtime/server/api/_movk/session.post.js +0 -18
- package/dist/runtime/types/auth.d.ts +0 -34
- package/dist/runtime/types/auto-form-renderer.d.ts +0 -22
- package/dist/runtime/types/components.d.ts +0 -43
- package/dist/runtime/types/components.js +0 -0
- package/dist/runtime/utils/auto-form.d.ts +0 -3
- package/dist/runtime/utils/auto-form.js +0 -18
- /package/dist/runtime/{utils → auto-form}/reactive-utils.js +0 -0
- /package/dist/runtime/types/{auto-form-renderer.js → theme.js} +0 -0
|
@@ -1,18 +1,69 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FetchContext, FetchResponse } from 'ofetch';
|
|
2
|
+
import type { ApiInstance, MovkApiPublicConfig, EndpointPrivateConfig, MovkApiFullConfig } from './api.js';
|
|
3
|
+
interface MovkFontProviderConfig {
|
|
4
|
+
/**
|
|
5
|
+
* CDN 基础 URL
|
|
6
|
+
* @see 'https://fonts.nuxt.com/get-started/providers#custom-providers'
|
|
7
|
+
* @example 'https://cdn.org/fonts'
|
|
8
|
+
*/
|
|
9
|
+
cdn: string;
|
|
10
|
+
/**
|
|
11
|
+
* 需要加载的字重,默认全部加载
|
|
12
|
+
* @example [300, 400, 500, 700]
|
|
13
|
+
*/
|
|
14
|
+
weights?: number[];
|
|
15
|
+
}
|
|
2
16
|
export interface ModuleOptions {
|
|
3
17
|
/**
|
|
4
18
|
* 组件前缀
|
|
5
|
-
* @
|
|
19
|
+
* @defaultValue 'M'
|
|
6
20
|
*/
|
|
7
21
|
prefix?: string;
|
|
8
|
-
/**
|
|
9
|
-
* API 模块配置
|
|
10
|
-
*/
|
|
22
|
+
/** API 模块配置 */
|
|
11
23
|
api?: MovkApiFullConfig;
|
|
24
|
+
/** 主题系统配置 */
|
|
25
|
+
theme?: {
|
|
26
|
+
/**
|
|
27
|
+
* 是否启用主题模块(appConfig 默认值、theme plugin、ThemePicker 组件)
|
|
28
|
+
* @defaultValue true
|
|
29
|
+
*/
|
|
30
|
+
enabled?: boolean;
|
|
31
|
+
};
|
|
32
|
+
/** 字体提供器配置 */
|
|
33
|
+
fonts?: {
|
|
34
|
+
/**
|
|
35
|
+
* 是否启用字体模块
|
|
36
|
+
* @defaultValue true
|
|
37
|
+
*/
|
|
38
|
+
enabled?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* 阿里巴巴普惠体字体
|
|
41
|
+
* @defaultValue 'https://cdn.mhaibaraai.cn/fonts'
|
|
42
|
+
*/
|
|
43
|
+
alibabaPuhuiti?: MovkFontProviderConfig;
|
|
44
|
+
};
|
|
12
45
|
}
|
|
13
|
-
declare module '
|
|
46
|
+
declare module 'nuxt/app' {
|
|
14
47
|
interface NuxtApp {
|
|
15
|
-
$api:
|
|
48
|
+
$api: ApiInstance;
|
|
49
|
+
}
|
|
50
|
+
interface RuntimeNuxtHooks {
|
|
51
|
+
/** 请求发送前(认证注入后) */
|
|
52
|
+
'movk:api:request': (context: FetchContext) => void | Promise<void>;
|
|
53
|
+
/** 响应成功(业务检查 + 解包后) */
|
|
54
|
+
'movk:api:response': (context: FetchContext & {
|
|
55
|
+
response: FetchResponse<any>;
|
|
56
|
+
}) => void | Promise<void>;
|
|
57
|
+
/** 任何错误(业务错误 + HTTP 错误) */
|
|
58
|
+
'movk:api:error': (context: FetchContext & {
|
|
59
|
+
response: FetchResponse<any>;
|
|
60
|
+
}) => void | Promise<void>;
|
|
61
|
+
/** 401 专用(支持 handled 标记跳过默认行为) */
|
|
62
|
+
'movk:api:unauthorized': (context: FetchContext & {
|
|
63
|
+
response: FetchResponse<any>;
|
|
64
|
+
}, result: {
|
|
65
|
+
handled: boolean;
|
|
66
|
+
}) => void | Promise<void>;
|
|
16
67
|
}
|
|
17
68
|
}
|
|
18
69
|
declare module 'nuxt/schema' {
|
|
@@ -26,14 +77,20 @@ declare module 'nuxt/schema' {
|
|
|
26
77
|
movkApi: MovkApiPublicConfig;
|
|
27
78
|
}
|
|
28
79
|
interface RuntimeConfig {
|
|
29
|
-
movkApi:
|
|
80
|
+
movkApi: {
|
|
81
|
+
endpoints?: Record<string, EndpointPrivateConfig>;
|
|
82
|
+
};
|
|
30
83
|
}
|
|
31
84
|
interface AppConfig {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
85
|
+
ui: {
|
|
86
|
+
colors: {
|
|
87
|
+
primary: string;
|
|
88
|
+
neutral: string;
|
|
89
|
+
[key: string]: string;
|
|
90
|
+
};
|
|
91
|
+
icons: Record<string, string>;
|
|
37
92
|
};
|
|
93
|
+
toaster?: import('@nuxt/ui').ToasterProps | null;
|
|
38
94
|
}
|
|
39
95
|
}
|
|
96
|
+
export {};
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import type { AutoFormFieldContext, AutoFormFieldSlots, AutoFormNestedCollapsible } from '#movk/types
|
|
2
|
-
import type { ClassNameValue } from 'tailwind-merge'
|
|
1
|
+
import type { AutoFormFieldContext, AutoFormFieldSlots, AutoFormNestedCollapsible, ClassNameValue } from '#movk/types'
|
|
3
2
|
import type { ReactiveValue } from '@movk/core'
|
|
4
3
|
|
|
5
4
|
type ZodValue<T, CTX = AutoFormFieldContext> = ReactiveValue<T, CTX>
|
|
6
5
|
|
|
7
6
|
export interface ZodAutoFormFieldMeta {
|
|
8
7
|
/**
|
|
9
|
-
*
|
|
8
|
+
* 当前字段渲染使用的元素或组件。
|
|
10
9
|
* @defaultValue 'div'
|
|
11
10
|
*/
|
|
12
11
|
as?: ZodValue<any>
|
|
13
|
-
/**
|
|
12
|
+
/** 表单字段名,同时用于匹配表单错误。 */
|
|
14
13
|
name?: ZodValue<string>
|
|
15
|
-
/**
|
|
14
|
+
/** 用于匹配表单错误名称的正则表达式。 */
|
|
16
15
|
errorPattern?: ZodValue<RegExp>
|
|
17
16
|
label?: ZodValue<string>
|
|
18
17
|
description?: ZodValue<string>
|
|
@@ -20,22 +19,24 @@ export interface ZodAutoFormFieldMeta {
|
|
|
20
19
|
error?: ZodValue<boolean | string>
|
|
21
20
|
hint?: ZodValue<string>
|
|
22
21
|
/**
|
|
22
|
+
* 字段尺寸。
|
|
23
23
|
* @defaultValue 'md'
|
|
24
24
|
*/
|
|
25
25
|
size?: ZodValue<'md' | 'xs' | 'sm' | 'lg' | 'xl'>
|
|
26
26
|
/**
|
|
27
|
+
* 是否必填。
|
|
27
28
|
* @defaultValue true
|
|
28
29
|
*/
|
|
29
30
|
required?: ZodValue<boolean>
|
|
30
|
-
/**
|
|
31
|
+
/** 是否在输入时立即触发校验(而不是等待 blur 事件)。 */
|
|
31
32
|
eagerValidation?: ZodValue<boolean>
|
|
32
33
|
/**
|
|
33
|
-
*
|
|
34
|
+
* 输入事件触发后,延迟多少毫秒执行表单校验。
|
|
34
35
|
* @defaultValue `300`
|
|
35
36
|
*/
|
|
36
37
|
validateOnInputDelay?: ZodValue<number>
|
|
37
38
|
class?: ZodValue<any>
|
|
38
|
-
ui?: ZodValue<{ root?: ClassNameValue, wrapper?: ClassNameValue, labelWrapper?: ClassNameValue, label?:
|
|
39
|
+
ui?: ZodValue<{ root?: ClassNameValue, wrapper?: ClassNameValue, labelWrapper?: ClassNameValue, label?: ClassNameValue, container?: ClassNameValue, description?: ClassNameValue, error?: ClassNameValue, hint?: ClassNameValue, help?: ClassNameValue }>
|
|
39
40
|
/**
|
|
40
41
|
* @see https://ui4.nuxt.com/docs/components/form-field#slots
|
|
41
42
|
*/
|
|
@@ -46,7 +47,7 @@ export interface ZodAutoFormFieldMeta {
|
|
|
46
47
|
/** 是否隐藏 */
|
|
47
48
|
hidden?: ZodValue<boolean>
|
|
48
49
|
/**
|
|
49
|
-
*
|
|
50
|
+
* 对象字段折叠配置。
|
|
50
51
|
*/
|
|
51
52
|
collapsible?: ZodValue<AutoFormNestedCollapsible>
|
|
52
53
|
|
|
@@ -54,7 +55,7 @@ export interface ZodAutoFormFieldMeta {
|
|
|
54
55
|
[key: string]: unknown
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
declare module 'zod
|
|
58
|
+
declare module 'zod' {
|
|
58
59
|
|
|
59
60
|
interface GlobalMeta extends ZodAutoFormFieldMeta { }
|
|
60
61
|
|
|
@@ -1,79 +1,58 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ApiResponse, ApiError, ApiResponseConfig, ApiToastConfig, RequestToastOptions, ResolvedEndpointConfig } from '../types/api.js';
|
|
1
|
+
import type { ApiResponse, ApiError, ApiResponseConfig, ApiToastConfig, RequestToastOptions, ResolvedEndpointConfig, MovkApiPublicConfig } from '../types/api.js';
|
|
3
2
|
/**
|
|
4
|
-
* 判断API响应是否业务成功
|
|
5
|
-
* @param response - API响应对象
|
|
6
|
-
* @param config - 响应配置(包含codeKey和successCodes)
|
|
3
|
+
* 判断 API 响应是否业务成功
|
|
4
|
+
* @param response - API 响应对象
|
|
5
|
+
* @param config - 响应配置(包含 codeKey 和 successCodes)
|
|
7
6
|
* @returns 是否业务成功
|
|
8
7
|
*/
|
|
9
8
|
export declare function isBusinessSuccess(response: ApiResponse, config?: Partial<ApiResponseConfig>): boolean;
|
|
10
9
|
/**
|
|
11
|
-
* 从API响应中提取消息内容
|
|
12
|
-
* @param response - API响应对象
|
|
13
|
-
* @param config - 响应配置(包含messageKey)
|
|
14
|
-
* @returns 消息字符串或undefined
|
|
10
|
+
* 从 API 响应中提取消息内容
|
|
11
|
+
* @param response - API 响应对象
|
|
12
|
+
* @param config - 响应配置(包含 messageKey)
|
|
13
|
+
* @returns 消息字符串或 undefined
|
|
15
14
|
*/
|
|
16
15
|
export declare function extractMessage(response: ApiResponse, config?: Partial<ApiResponseConfig>): string | undefined;
|
|
17
16
|
/**
|
|
18
|
-
* 从API响应中提取业务数据
|
|
19
|
-
* @param response - API响应对象
|
|
20
|
-
* @param config - 响应配置(包含dataKey)
|
|
17
|
+
* 从 API 响应中提取业务数据
|
|
18
|
+
* @param response - API 响应对象
|
|
19
|
+
* @param config - 响应配置(包含 dataKey)
|
|
21
20
|
* @returns 业务数据
|
|
22
21
|
*/
|
|
23
|
-
export declare function extractData
|
|
22
|
+
export declare function extractData(response: ApiResponse, config?: Partial<ApiResponseConfig>): unknown;
|
|
24
23
|
/**
|
|
25
24
|
* 创建业务错误对象
|
|
26
|
-
* @param response - API响应对象
|
|
25
|
+
* @param response - API 响应对象
|
|
27
26
|
* @param message - 错误消息(可选)
|
|
28
27
|
* @returns 业务错误对象
|
|
29
28
|
*/
|
|
30
29
|
export declare function createApiError(response: ApiResponse, message?: string): ApiError;
|
|
31
30
|
/**
|
|
32
|
-
* 提取Toast消息内容
|
|
33
|
-
* @param toast - Toast配置选项
|
|
31
|
+
* 提取 Toast 消息内容
|
|
32
|
+
* @param toast - Toast 配置选项
|
|
34
33
|
* @param type - 消息类型
|
|
35
34
|
* @param fallback - 默认消息
|
|
36
35
|
* @returns 最终显示的消息内容
|
|
37
36
|
*/
|
|
38
37
|
export declare function extractToastMessage(toast: RequestToastOptions | false | undefined, type: 'success' | 'error', fallback: string): string;
|
|
39
38
|
/**
|
|
40
|
-
* 显示Toast提示
|
|
39
|
+
* 显示 Toast 提示
|
|
41
40
|
* @param type - 提示类型
|
|
42
41
|
* @param message - 提示消息
|
|
43
|
-
* @param requestOptions - 请求级别的Toast配置
|
|
44
|
-
* @param globalConfig - 全局Toast配置
|
|
42
|
+
* @param requestOptions - 请求级别的 Toast 配置
|
|
43
|
+
* @param globalConfig - 全局 Toast 配置
|
|
45
44
|
*/
|
|
46
45
|
export declare function showToast(type: 'success' | 'error', message: string | undefined, requestOptions: RequestToastOptions | false | undefined, globalConfig: Partial<ApiToastConfig>): void;
|
|
47
|
-
interface CreateTransformOptions<ResT, DataT = ResT> {
|
|
48
|
-
skipBusinessCheck: boolean;
|
|
49
|
-
userTransform?: (data: ResT) => DataT;
|
|
50
|
-
successConfig: Partial<ApiResponseConfig>;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* 创建响应转换函数
|
|
54
|
-
* @description 用于 useFetch 的 transform 选项,处理业务状态码检查和数据提取
|
|
55
|
-
* @param options - 转换选项(包含skipBusinessCheck、userTransform、successConfig)
|
|
56
|
-
* @returns 响应转换函数
|
|
57
|
-
*/
|
|
58
|
-
export declare function createTransform<ResT, DataT = ResT>(options: CreateTransformOptions<ResT, DataT>): (response: ApiResponse<ResT>) => DataT;
|
|
59
|
-
type HookFunction = (context: FetchContext) => void | Promise<void>;
|
|
60
|
-
/**
|
|
61
|
-
* 合并多个钩子函数为一个
|
|
62
|
-
* @param hooks - 钩子函数数组
|
|
63
|
-
* @returns 合并后的钩子函数
|
|
64
|
-
*/
|
|
65
|
-
export declare function mergeHooks(...hooks: (HookFunction | undefined)[]): HookFunction;
|
|
66
|
-
/**
|
|
67
|
-
* 合并内置钩子和用户钩子
|
|
68
|
-
* @param builtinHooks - 内置钩子集合
|
|
69
|
-
* @param userHooks - 用户自定义钩子集合
|
|
70
|
-
* @returns 合并后的完整钩子集合
|
|
71
|
-
*/
|
|
72
|
-
export declare function mergeFetchHooks(builtinHooks: Partial<FetchHooks>, userHooks: Partial<FetchHooks>): FetchHooks;
|
|
73
46
|
/**
|
|
74
47
|
* 获取认证请求头
|
|
75
|
-
* @param config -
|
|
48
|
+
* @param config - 已解析的端点配置(或至少包含 auth 字段)
|
|
76
49
|
* @returns 认证请求头对象
|
|
77
50
|
*/
|
|
78
|
-
export declare function getAuthHeaders(config: ResolvedEndpointConfig): Record<string, string>;
|
|
79
|
-
|
|
51
|
+
export declare function getAuthHeaders(config: Pick<ResolvedEndpointConfig, 'auth'>): Record<string, string>;
|
|
52
|
+
/**
|
|
53
|
+
* 从 publicConfig 解析端点配置(合并全局默认值)
|
|
54
|
+
* @param publicConfig - 模块公共配置
|
|
55
|
+
* @param endpoint - 端点名称(可选,默认使用 defaultEndpoint)
|
|
56
|
+
* @returns 已解析的端点配置(含 baseURL、auth、toast、response)
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveEndpointConfig(publicConfig: MovkApiPublicConfig, endpoint?: string): Pick<ResolvedEndpointConfig, 'baseURL' | 'auth' | 'toast' | 'response'>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getPath } from "@movk/core";
|
|
2
|
+
import defu from "defu";
|
|
2
3
|
import { useNuxtApp, useToast, useUserSession } from "#imports";
|
|
3
4
|
export function isBusinessSuccess(response, config = {}) {
|
|
4
5
|
const codeKey = config.codeKey || "code";
|
|
@@ -12,7 +13,7 @@ export function extractMessage(response, config = {}) {
|
|
|
12
13
|
}
|
|
13
14
|
export function extractData(response, config = {}) {
|
|
14
15
|
const dataKey = config.dataKey || "data";
|
|
15
|
-
return response[dataKey] ?? response
|
|
16
|
+
return response[dataKey] ?? response;
|
|
16
17
|
}
|
|
17
18
|
export function createApiError(response, message) {
|
|
18
19
|
const error = new Error(message || "\u8BF7\u6C42\u5931\u8D25");
|
|
@@ -24,7 +25,7 @@ export function createApiError(response, message) {
|
|
|
24
25
|
function getToast() {
|
|
25
26
|
try {
|
|
26
27
|
const nuxtApp = useNuxtApp();
|
|
27
|
-
return nuxtApp.runWithContext(() => useToast());
|
|
28
|
+
return nuxtApp.vueApp.runWithContext(() => useToast());
|
|
28
29
|
} catch {
|
|
29
30
|
return null;
|
|
30
31
|
}
|
|
@@ -51,54 +52,10 @@ export function showToast(type, message, requestOptions, globalConfig) {
|
|
|
51
52
|
...requestTypeConfig
|
|
52
53
|
});
|
|
53
54
|
}
|
|
54
|
-
export function createTransform(options) {
|
|
55
|
-
const { skipBusinessCheck, userTransform, successConfig } = options;
|
|
56
|
-
return (response) => {
|
|
57
|
-
if (!skipBusinessCheck && !isBusinessSuccess(response, successConfig)) {
|
|
58
|
-
throw createApiError(response, extractMessage(response, successConfig));
|
|
59
|
-
}
|
|
60
|
-
const unwrappedData = extractData(response, successConfig);
|
|
61
|
-
if (userTransform) {
|
|
62
|
-
return userTransform(unwrappedData);
|
|
63
|
-
}
|
|
64
|
-
return unwrappedData;
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
export function mergeHooks(...hooks) {
|
|
68
|
-
const validHooks = hooks.filter((h) => typeof h === "function");
|
|
69
|
-
if (validHooks.length === 0) return () => {
|
|
70
|
-
};
|
|
71
|
-
if (validHooks.length === 1) return validHooks[0];
|
|
72
|
-
return async (context) => {
|
|
73
|
-
for (const hook of validHooks) {
|
|
74
|
-
await hook(context);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
export function mergeFetchHooks(builtinHooks, userHooks) {
|
|
79
|
-
return {
|
|
80
|
-
onRequest: mergeHooks(
|
|
81
|
-
builtinHooks.onRequest,
|
|
82
|
-
userHooks.onRequest
|
|
83
|
-
),
|
|
84
|
-
onRequestError: mergeHooks(
|
|
85
|
-
builtinHooks.onRequestError,
|
|
86
|
-
userHooks.onRequestError
|
|
87
|
-
),
|
|
88
|
-
onResponse: mergeHooks(
|
|
89
|
-
builtinHooks.onResponse,
|
|
90
|
-
userHooks.onResponse
|
|
91
|
-
),
|
|
92
|
-
onResponseError: mergeHooks(
|
|
93
|
-
builtinHooks.onResponseError,
|
|
94
|
-
userHooks.onResponseError
|
|
95
|
-
)
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
55
|
function getUserSession() {
|
|
99
56
|
try {
|
|
100
57
|
const nuxtApp = useNuxtApp();
|
|
101
|
-
return nuxtApp.runWithContext(() => useUserSession());
|
|
58
|
+
return nuxtApp.vueApp.runWithContext(() => useUserSession());
|
|
102
59
|
} catch {
|
|
103
60
|
return null;
|
|
104
61
|
}
|
|
@@ -125,3 +82,17 @@ export function getAuthHeaders(config) {
|
|
|
125
82
|
}
|
|
126
83
|
return headers;
|
|
127
84
|
}
|
|
85
|
+
export function resolveEndpointConfig(publicConfig, endpoint) {
|
|
86
|
+
const endpointName = endpoint || publicConfig.defaultEndpoint || "default";
|
|
87
|
+
const endpointConfig = publicConfig.endpoints[endpointName];
|
|
88
|
+
if (!endpointConfig) {
|
|
89
|
+
console.warn(`[Movk API] Endpoint "${endpointName}" not found, using default`);
|
|
90
|
+
return resolveEndpointConfig(publicConfig, publicConfig.defaultEndpoint || "default");
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
baseURL: endpointConfig.baseURL || "",
|
|
94
|
+
auth: defu(endpointConfig.auth, publicConfig.auth),
|
|
95
|
+
toast: defu(endpointConfig.toast, publicConfig.toast),
|
|
96
|
+
response: defu(endpointConfig.response, publicConfig.response)
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
export async function getPackageJsonMetadata(dir) {
|
|
4
|
+
try {
|
|
5
|
+
const packageJson = await readFile(resolve(dir, "package.json"), "utf-8");
|
|
6
|
+
const parsed = JSON.parse(packageJson);
|
|
7
|
+
return {
|
|
8
|
+
name: parsed.name,
|
|
9
|
+
description: parsed.description
|
|
10
|
+
};
|
|
11
|
+
} catch {
|
|
12
|
+
return {
|
|
13
|
+
name: "docs"
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@movk/nuxt",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
5
|
-
"packageManager": "pnpm@10.
|
|
6
|
-
"description": "
|
|
4
|
+
"version": "1.2.0",
|
|
5
|
+
"packageManager": "pnpm@10.33.0",
|
|
6
|
+
"description": "Nuxt 4 modular engineering suite — schema-driven auto forms (Zod v4), API integration with auth & progress tracking, standalone UI components, and utility composables",
|
|
7
7
|
"author": "YiXuan <mhaibaraai@gmail.com>",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"repository": {
|
|
@@ -76,57 +76,58 @@
|
|
|
76
76
|
"dist"
|
|
77
77
|
],
|
|
78
78
|
"peerDependencies": {
|
|
79
|
-
"@nuxt/ui": ">=4.
|
|
80
|
-
"zod": ">=4.3.
|
|
79
|
+
"@nuxt/ui": ">=4.6.0",
|
|
80
|
+
"zod": ">=4.3.6"
|
|
81
81
|
},
|
|
82
82
|
"scripts": {
|
|
83
83
|
"prepack": "pnpm build",
|
|
84
84
|
"build": "nuxt-module-build build",
|
|
85
|
-
"dev": "nuxt dev
|
|
86
|
-
"dev:
|
|
87
|
-
"dev:
|
|
85
|
+
"dev": "nuxt dev playgrounds/play",
|
|
86
|
+
"dev:build": "nuxt build playgrounds/play",
|
|
87
|
+
"dev:dashboard": "nuxt dev playgrounds/dashboard",
|
|
88
|
+
"dev:dashboard:build": "nuxt build playgrounds/dashboard",
|
|
89
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playgrounds/play && nuxt prepare playgrounds/dashboard && nuxt prepare docs",
|
|
88
90
|
"docs": "nuxt dev docs",
|
|
89
91
|
"docs:build": "nuxt build docs",
|
|
90
92
|
"release": "release-it && npm publish",
|
|
91
93
|
"lint": "eslint .",
|
|
92
94
|
"lint:fix": "eslint . --fix",
|
|
93
|
-
"typecheck": "vue-tsc --noEmit && nuxt typecheck
|
|
95
|
+
"typecheck": "vue-tsc --noEmit && nuxt typecheck playgrounds/play && nuxt typecheck playgrounds/dashboard && nuxt typecheck docs",
|
|
94
96
|
"clean": "movk-clean",
|
|
95
97
|
"test": "vitest"
|
|
96
98
|
},
|
|
97
99
|
"dependencies": {
|
|
98
|
-
"@iconify-json/lucide": "^1.2.
|
|
100
|
+
"@iconify-json/lucide": "^1.2.101",
|
|
99
101
|
"@iconify-json/ph": "^1.2.2",
|
|
100
|
-
"@iconify-json/tabler": "^1.2.
|
|
101
|
-
"@internationalized/date": "^3.
|
|
102
|
-
"@movk/core": "^1.
|
|
102
|
+
"@iconify-json/tabler": "^1.2.33",
|
|
103
|
+
"@internationalized/date": "^3.12.0",
|
|
104
|
+
"@movk/core": "^1.2.3",
|
|
103
105
|
"@nuxt/image": "^2.0.0",
|
|
104
|
-
"@nuxt/ui": "^4.
|
|
105
|
-
"@vueuse/core": "^14.1
|
|
106
|
-
"@vueuse/nuxt": "^14.1
|
|
107
|
-
"defu": "^6.1.
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"nuxt-
|
|
106
|
+
"@nuxt/ui": "^4.6.1",
|
|
107
|
+
"@vueuse/core": "^14.2.1",
|
|
108
|
+
"@vueuse/nuxt": "^14.2.1",
|
|
109
|
+
"defu": "^6.1.6",
|
|
110
|
+
"maska": "^3.2.0",
|
|
111
|
+
"motion-v": "^2.2.0",
|
|
112
|
+
"nuxt-auth-utils": "^0.5.29",
|
|
113
|
+
"nuxt-og-image": "^6.3.2",
|
|
114
|
+
"reka-ui": "^2.9.3",
|
|
111
115
|
"scule": "^1.3.0",
|
|
112
|
-
"tailwindcss": "^4.
|
|
113
|
-
"
|
|
116
|
+
"tailwindcss": "^4.2.2",
|
|
117
|
+
"unifont": "^0.7.4",
|
|
118
|
+
"zod": "^4.3.6"
|
|
114
119
|
},
|
|
115
120
|
"devDependencies": {
|
|
116
|
-
"@nuxt/
|
|
117
|
-
"@nuxt/
|
|
118
|
-
"@nuxt/kit": "^4.2.2",
|
|
121
|
+
"@nuxt/eslint-config": "^1.15.2",
|
|
122
|
+
"@nuxt/kit": "^4.4.2",
|
|
119
123
|
"@nuxt/module-builder": "^1.0.2",
|
|
120
|
-
"@nuxt/schema": "^4.
|
|
121
|
-
"@nuxt/test-utils": "^3.23.0",
|
|
124
|
+
"@nuxt/schema": "^4.4.2",
|
|
122
125
|
"@release-it/bumper": "^7.0.5",
|
|
123
|
-
"@release-it/conventional-changelog": "^10.0.
|
|
124
|
-
"
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
"
|
|
129
|
-
"vitest": "^4.0.17",
|
|
130
|
-
"vue-tsc": "^3.2.2"
|
|
126
|
+
"@release-it/conventional-changelog": "^10.0.6",
|
|
127
|
+
"eslint": "^10.2.0",
|
|
128
|
+
"nuxt": "^4.4.2",
|
|
129
|
+
"typescript": "^6.0.2",
|
|
130
|
+
"vitest": "^4.1.2",
|
|
131
|
+
"vue-tsc": "^3.2.6"
|
|
131
132
|
}
|
|
132
133
|
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { UseApiAuthReturn } from '../types/api.js';
|
|
2
|
-
/**
|
|
3
|
-
* API 认证 Composable
|
|
4
|
-
*
|
|
5
|
-
* 提供完整的登录、登出、刷新用户信息等功能,
|
|
6
|
-
* 与 nuxt-auth-utils 无缝集成。
|
|
7
|
-
*
|
|
8
|
-
* @returns UseApiAuthReturn 认证相关方法和状态
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* const { login, clear, loggedIn, user } = useApiAuth()
|
|
13
|
-
*
|
|
14
|
-
* // 基础登录
|
|
15
|
-
* await login({
|
|
16
|
-
* loginPath: '/auth/login',
|
|
17
|
-
* credentials: { username: 'admin', password: '123456' }
|
|
18
|
-
* })
|
|
19
|
-
*
|
|
20
|
-
* // 登录后获取用户信息
|
|
21
|
-
* await login({
|
|
22
|
-
* loginPath: '/auth/login',
|
|
23
|
-
* credentials: { username: 'admin', password: '123456' },
|
|
24
|
-
* userInfoPath: '/auth/me'
|
|
25
|
-
* })
|
|
26
|
-
*
|
|
27
|
-
* // 自定义 token 提取和 session 构建
|
|
28
|
-
* await login({
|
|
29
|
-
* loginPath: '/auth/login',
|
|
30
|
-
* credentials: { username: 'admin', password: '123456' },
|
|
31
|
-
* tokenExtractor: (res) => res.data?.accessToken,
|
|
32
|
-
* sessionBuilder: (user, token) => ({
|
|
33
|
-
* user: { id: user.id, name: user.name },
|
|
34
|
-
* secure: { token, permissions: user.permissions }
|
|
35
|
-
* })
|
|
36
|
-
* })
|
|
37
|
-
*
|
|
38
|
-
* // 登出
|
|
39
|
-
* await clear()
|
|
40
|
-
*
|
|
41
|
-
* // 响应式状态
|
|
42
|
-
* if (loggedIn.value) {
|
|
43
|
-
* console.log('当前用户:', user.value)
|
|
44
|
-
* }
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export declare function useApiAuth(): UseApiAuthReturn;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { getPath } from "@movk/core";
|
|
2
|
-
import { useNuxtApp, useRuntimeConfig, useUserSession } from "#imports";
|
|
3
|
-
export function useApiAuth() {
|
|
4
|
-
const { $api } = useNuxtApp();
|
|
5
|
-
const userSession = useUserSession();
|
|
6
|
-
const moduleConfig = useRuntimeConfig().public.movkApi;
|
|
7
|
-
const buildAuthHeader = (token, authConfig = {}) => {
|
|
8
|
-
const tokenType = authConfig.tokenType === "Custom" ? authConfig.customTokenType || "" : authConfig.tokenType || "Bearer";
|
|
9
|
-
return tokenType ? `${tokenType} ${token}` : token;
|
|
10
|
-
};
|
|
11
|
-
const getHeaderName = (authConfig = {}) => {
|
|
12
|
-
return authConfig.headerName || "Authorization";
|
|
13
|
-
};
|
|
14
|
-
const defaultTokenExtractor = (response) => {
|
|
15
|
-
return getPath(response, "data.token") ?? getPath(response, "data.accessToken") ?? getPath(response, "token");
|
|
16
|
-
};
|
|
17
|
-
const defaultSessionBuilder = (user, token) => ({
|
|
18
|
-
user,
|
|
19
|
-
token,
|
|
20
|
-
loggedInAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21
|
-
});
|
|
22
|
-
async function login(options) {
|
|
23
|
-
const {
|
|
24
|
-
loginPath,
|
|
25
|
-
credentials,
|
|
26
|
-
userInfoPath,
|
|
27
|
-
tokenExtractor = defaultTokenExtractor,
|
|
28
|
-
sessionBuilder = defaultSessionBuilder,
|
|
29
|
-
endpoint
|
|
30
|
-
} = options;
|
|
31
|
-
const api = endpoint ? $api.use(endpoint) : $api;
|
|
32
|
-
const loginResponse = await api.$fetch(loginPath, {
|
|
33
|
-
method: "POST",
|
|
34
|
-
body: credentials
|
|
35
|
-
});
|
|
36
|
-
const token = tokenExtractor(loginResponse);
|
|
37
|
-
if (!token) {
|
|
38
|
-
throw new Error("Login failed: token not found in response");
|
|
39
|
-
}
|
|
40
|
-
let userInfo;
|
|
41
|
-
if (userInfoPath) {
|
|
42
|
-
const endpointConfig = api.getConfig();
|
|
43
|
-
const authConfig = endpointConfig.auth || moduleConfig.auth || {};
|
|
44
|
-
const headerName = getHeaderName(authConfig);
|
|
45
|
-
const headerValue = buildAuthHeader(token, authConfig);
|
|
46
|
-
const userResponse = await api.$fetch(userInfoPath, {
|
|
47
|
-
headers: { [headerName]: headerValue },
|
|
48
|
-
context: { toast: false }
|
|
49
|
-
});
|
|
50
|
-
userInfo = getPath(userResponse, "data") ?? userResponse;
|
|
51
|
-
} else {
|
|
52
|
-
userInfo = getPath(loginResponse, "data") ?? loginResponse;
|
|
53
|
-
}
|
|
54
|
-
const sessionData = sessionBuilder(userInfo, token);
|
|
55
|
-
await $fetch("/api/_movk/session", {
|
|
56
|
-
method: "POST",
|
|
57
|
-
body: sessionData
|
|
58
|
-
});
|
|
59
|
-
await userSession.fetch();
|
|
60
|
-
return { user: userInfo, token };
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
login,
|
|
64
|
-
...userSession
|
|
65
|
-
};
|
|
66
|
-
}
|