@movk/nuxt 0.1.1 → 1.0.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.
Files changed (60) hide show
  1. package/README.md +84 -9
  2. package/dist/module.d.mts +11 -0
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +29 -3
  5. package/dist/runtime/components/AutoForm.d.vue.ts +12 -6
  6. package/dist/runtime/components/AutoForm.vue +3 -1
  7. package/dist/runtime/components/AutoForm.vue.d.ts +12 -6
  8. package/dist/runtime/components/ColorChooser.d.vue.ts +11 -5
  9. package/dist/runtime/components/ColorChooser.vue.d.ts +11 -5
  10. package/dist/runtime/components/DatePicker.d.vue.ts +14 -5
  11. package/dist/runtime/components/DatePicker.vue.d.ts +14 -5
  12. package/dist/runtime/components/StarRating.d.vue.ts +7 -7
  13. package/dist/runtime/components/StarRating.vue.d.ts +7 -7
  14. package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.d.vue.ts +6 -4
  15. package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.vue.d.ts +6 -4
  16. package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.d.vue.ts +6 -4
  17. package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.vue.d.ts +6 -4
  18. package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.d.vue.ts +6 -4
  19. package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.vue.d.ts +6 -4
  20. package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.d.vue.ts +6 -4
  21. package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.vue.d.ts +6 -4
  22. package/dist/runtime/components/input/WithCharacterLimit.d.vue.ts +11 -5
  23. package/dist/runtime/components/input/WithCharacterLimit.vue.d.ts +11 -5
  24. package/dist/runtime/components/input/WithClear.d.vue.ts +12 -5
  25. package/dist/runtime/components/input/WithClear.vue.d.ts +12 -5
  26. package/dist/runtime/components/input/WithCopy.d.vue.ts +12 -5
  27. package/dist/runtime/components/input/WithCopy.vue.d.ts +12 -5
  28. package/dist/runtime/components/input/WithPasswordToggle.d.vue.ts +11 -5
  29. package/dist/runtime/components/input/WithPasswordToggle.vue.d.ts +11 -5
  30. package/dist/runtime/composables/useApiAuth.d.ts +47 -0
  31. package/dist/runtime/composables/useApiAuth.js +66 -0
  32. package/dist/runtime/composables/useApiFetch.d.ts +42 -0
  33. package/dist/runtime/composables/useApiFetch.js +43 -0
  34. package/dist/runtime/composables/useAutoForm.d.ts +874 -54
  35. package/dist/runtime/composables/useClientApiFetch.d.ts +24 -0
  36. package/dist/runtime/composables/useClientApiFetch.js +8 -0
  37. package/dist/runtime/composables/useDateFormatter.d.ts +21 -7
  38. package/dist/runtime/composables/useDateFormatter.js +92 -57
  39. package/dist/runtime/composables/useDownloadWithProgress.d.ts +48 -0
  40. package/dist/runtime/composables/useDownloadWithProgress.js +85 -0
  41. package/dist/runtime/composables/useUploadWithProgress.d.ts +52 -0
  42. package/dist/runtime/composables/useUploadWithProgress.js +117 -0
  43. package/dist/runtime/plugins/api.factory.d.ts +2 -0
  44. package/dist/runtime/plugins/api.factory.js +188 -0
  45. package/dist/runtime/schemas/api.d.ts +354 -0
  46. package/dist/runtime/schemas/api.js +212 -0
  47. package/dist/runtime/server/api/_movk/session.post.d.ts +10 -0
  48. package/dist/runtime/server/api/_movk/session.post.js +18 -0
  49. package/dist/runtime/types/api.d.ts +218 -0
  50. package/dist/runtime/types/api.js +8 -0
  51. package/dist/runtime/types/auth.d.ts +34 -0
  52. package/dist/runtime/types/auto-form-renderer.d.ts +14 -22
  53. package/dist/runtime/types/auto-form-renderer.js +0 -0
  54. package/dist/runtime/types/components.d.ts +29 -41
  55. package/dist/runtime/types/components.js +0 -0
  56. package/dist/runtime/types/index.d.ts +1 -0
  57. package/dist/runtime/types/index.js +3 -2
  58. package/dist/runtime/utils/api-utils.d.ts +64 -0
  59. package/dist/runtime/utils/api-utils.js +127 -0
  60. package/package.json +32 -25
@@ -0,0 +1,64 @@
1
+ import type { FetchContext, FetchHooks } from 'ofetch';
2
+ import type { ApiResponse, ApiError, ApiSuccessConfig, ApiToastConfig, RequestToastOptions, ResolvedEndpointConfig } from '../types/api.js';
3
+ /**
4
+ * 检查业务状态码是否成功
5
+ */
6
+ export declare function isBusinessSuccess(response: ApiResponse, config?: Partial<ApiSuccessConfig>): boolean;
7
+ /**
8
+ * 从响应中提取消息
9
+ */
10
+ export declare function extractMessage(response: ApiResponse, config?: Partial<ApiSuccessConfig>): string | undefined;
11
+ /**
12
+ * 从响应中提取数据
13
+ */
14
+ export declare function extractData<T>(response: ApiResponse<T>, config?: Partial<ApiSuccessConfig>): T;
15
+ /**
16
+ * 创建 API 业务错误
17
+ */
18
+ export declare function createApiError(response: ApiResponse, message?: string): ApiError;
19
+ /**
20
+ * 从请求选项中提取 Toast 消息
21
+ */
22
+ export declare function extractToastMessage(toast: RequestToastOptions | false | undefined, type: 'success' | 'error', fallback: string): string;
23
+ /**
24
+ * 显示 Toast 提示
25
+ */
26
+ export declare function showToast(type: 'success' | 'error', message: string | undefined, requestOptions: RequestToastOptions | false | undefined, globalConfig: Partial<ApiToastConfig>): void;
27
+ interface CreateTransformOptions<ResT, DataT = ResT> {
28
+ skipBusinessCheck: boolean;
29
+ userTransform?: (data: ResT) => DataT;
30
+ successConfig: Partial<ApiSuccessConfig>;
31
+ }
32
+ /**
33
+ * 创建 useFetch transform 函数
34
+ *
35
+ * 处理流程:
36
+ * 1. 业务状态码检查 → 失败时抛出 ApiError
37
+ * 2. 解包数据(提取 response.data)
38
+ * 3. 用户自定义 transform(接收解包后的数据)
39
+ */
40
+ export declare function createTransform<ResT, DataT = ResT>(options: CreateTransformOptions<ResT, DataT>): (response: ApiResponse<ResT>) => DataT;
41
+ type HookFunction = (context: FetchContext) => void | Promise<void>;
42
+ /**
43
+ * 合并多个 hook 函数,确保所有 hooks 都会执行
44
+ */
45
+ export declare function mergeHooks(...hooks: (HookFunction | undefined)[]): HookFunction;
46
+ /**
47
+ * 合并 FetchHooks 对象,每个 hook 类型单独合并
48
+ */
49
+ export declare function mergeFetchHooks(builtinHooks: Partial<FetchHooks>, userHooks: Partial<FetchHooks>): FetchHooks;
50
+ /**
51
+ * 获取认证 Headers
52
+ *
53
+ * 根据端点配置获取认证相关的 headers(如 Authorization)
54
+ * 用于原生 fetch/XHR 请求(如带进度的上传下载)
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const config = $api.getConfig()
59
+ * const authHeaders = getAuthHeaders(config)
60
+ * fetch(url, { headers: { ...headers, ...authHeaders } })
61
+ * ```
62
+ */
63
+ export declare function getAuthHeaders(config: ResolvedEndpointConfig): Record<string, string>;
64
+ export {};
@@ -0,0 +1,127 @@
1
+ import { getPath } from "@movk/core";
2
+ import { useNuxtApp, useToast, useUserSession } from "#imports";
3
+ export function isBusinessSuccess(response, config = {}) {
4
+ const codeKey = config.codeKey || "code";
5
+ const successCodes = config.successCodes || [200, 0];
6
+ const code = response[codeKey];
7
+ return successCodes.includes(code);
8
+ }
9
+ export function extractMessage(response, config = {}) {
10
+ const messageKey = config.messageKey || "message";
11
+ return response[messageKey] || response.message || response.msg;
12
+ }
13
+ export function extractData(response, config = {}) {
14
+ const dataKey = config.dataKey || "data";
15
+ return response[dataKey] ?? response.result ?? response;
16
+ }
17
+ export function createApiError(response, message) {
18
+ const error = new Error(message || "\u8BF7\u6C42\u5931\u8D25");
19
+ error.statusCode = Number(response.code || response.status || 500);
20
+ error.response = response;
21
+ error.isBusinessError = true;
22
+ return error;
23
+ }
24
+ function getToast() {
25
+ try {
26
+ const nuxtApp = useNuxtApp();
27
+ return nuxtApp.runWithContext(() => useToast());
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+ export function extractToastMessage(toast, type, fallback) {
33
+ if (toast === false) return fallback;
34
+ return (typeof toast === "object" ? toast?.[`${type}Message`] : void 0) || fallback;
35
+ }
36
+ export function showToast(type, message, requestOptions, globalConfig) {
37
+ if (globalConfig.enabled === false || requestOptions === false) return;
38
+ if (!message) return;
39
+ const typeConfig = globalConfig[type];
40
+ if (typeConfig?.show === false) return;
41
+ if (requestOptions?.[type] === false) return;
42
+ const toast = getToast();
43
+ if (!toast) return;
44
+ const requestTypeConfig = typeof requestOptions?.[type] === "object" ? requestOptions[type] : {};
45
+ toast.add({
46
+ icon: type === "success" ? "i-lucide-circle-check" : "i-lucide-circle-x",
47
+ title: message,
48
+ color: type === "success" ? "success" : "error",
49
+ duration: 3e3,
50
+ ...typeConfig && { ...typeConfig, show: void 0 },
51
+ ...requestTypeConfig
52
+ });
53
+ }
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
+ function getUserSession() {
99
+ try {
100
+ const nuxtApp = useNuxtApp();
101
+ return nuxtApp.runWithContext(() => useUserSession());
102
+ } catch {
103
+ return null;
104
+ }
105
+ }
106
+ function getTokenFromSession(tokenPath) {
107
+ const userSession = getUserSession();
108
+ if (!userSession?.session?.value) return null;
109
+ const sessionData = userSession.session.value;
110
+ return getPath(sessionData, tokenPath) || null;
111
+ }
112
+ function buildAuthHeaderValue(token, config) {
113
+ const tokenType = config.tokenType === "Custom" ? config.customTokenType || "" : config.tokenType || "Bearer";
114
+ return tokenType ? `${tokenType} ${token}` : token;
115
+ }
116
+ export function getAuthHeaders(config) {
117
+ const headers = {};
118
+ const authConfig = config.auth;
119
+ if (!authConfig.enabled) return headers;
120
+ const tokenPath = authConfig.sessionTokenPath || "token";
121
+ const token = getTokenFromSession(tokenPath);
122
+ if (token) {
123
+ const headerName = authConfig.headerName || "Authorization";
124
+ headers[headerName] = buildAuthHeaderValue(token, authConfig);
125
+ }
126
+ return headers;
127
+ }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@movk/nuxt",
3
3
  "type": "module",
4
- "version": "0.1.1",
5
- "packageManager": "pnpm@10.24.0",
6
- "description": "Schema-driven form and table generation module for Nuxt 4",
4
+ "version": "1.0.0",
5
+ "packageManager": "pnpm@10.26.1",
6
+ "description": "Modular engineering suite for Nuxt 4 with schema-driven forms, API integration, UI components and composables",
7
7
  "author": "YiXuan <mhaibaraai@gmail.com>",
8
8
  "license": "MIT",
9
9
  "repository": {
@@ -23,10 +23,16 @@
23
23
  "nuxt4",
24
24
  "zod",
25
25
  "form",
26
- "table",
27
26
  "auto-form",
28
27
  "schema-driven",
29
- "validation"
28
+ "validation",
29
+ "api",
30
+ "fetch",
31
+ "auth",
32
+ "upload",
33
+ "download",
34
+ "composables",
35
+ "ui-components"
30
36
  ],
31
37
  "exports": {
32
38
  ".": {
@@ -40,18 +46,18 @@
40
46
  "dist"
41
47
  ],
42
48
  "peerDependencies": {
43
- "zod": ">=4.1.13",
44
- "@nuxt/ui": ">=4.2.1"
49
+ "@nuxt/ui": ">=4.2.1",
50
+ "zod": ">=4.1.13"
45
51
  },
46
52
  "scripts": {
47
- "prepack": "nr build",
53
+ "prepack": "pnpm build",
48
54
  "build": "nuxt-module-build build",
49
55
  "dev": "nuxt dev playground",
50
56
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground && nuxt prepare docs",
51
57
  "dev:build": "nuxt build playground",
52
58
  "docs": "nuxt dev docs",
53
59
  "docs:build": "nuxt build docs",
54
- "release": "release-it && npm publish --access public",
60
+ "release": "release-it && npm publish",
55
61
  "lint": "eslint .",
56
62
  "lint:fix": "eslint . --fix",
57
63
  "typecheck": "vue-tsc --noEmit && nuxt typecheck playground",
@@ -59,35 +65,36 @@
59
65
  "test": "vitest"
60
66
  },
61
67
  "dependencies": {
62
- "@iconify-json/lucide": "^1.2.77",
63
- "@internationalized/date": "^3.10.0",
68
+ "@iconify-json/lucide": "^1.2.82",
69
+ "@internationalized/date": "^3.10.1",
64
70
  "@movk/core": "^1.0.2",
65
71
  "@nuxt/image": "^2.0.0",
66
- "@nuxt/ui": "^4.2.1",
72
+ "@nuxt/ui": "^4.3.0",
67
73
  "@vueuse/core": "^14.1.0",
68
74
  "@vueuse/nuxt": "^14.1.0",
69
75
  "defu": "^6.1.4",
70
- "tailwindcss": "^4.1.17",
76
+ "nuxt-auth-utils": "^0.5.26",
77
+ "tailwindcss": "^4.1.18",
71
78
  "scule": "^1.3.0",
72
- "zod": "^4.1.13"
79
+ "zod": "^4.2.1"
73
80
  },
74
81
  "devDependencies": {
75
- "@antfu/ni": "^27.0.1",
76
82
  "@nuxt/devtools": "^3.1.1",
77
- "@nuxt/eslint": "^1.11.0",
78
- "@nuxt/kit": "^4.2.1",
83
+ "@nuxt/eslint": "^1.12.1",
84
+ "@nuxt/kit": "^4.2.2",
79
85
  "@nuxt/module-builder": "^1.0.2",
80
- "@nuxt/schema": "^4.2.1",
81
- "@nuxt/test-utils": "^3.20.1",
86
+ "@nuxt/schema": "^4.2.2",
87
+ "@nuxt/test-utils": "^3.21.0",
82
88
  "@release-it/bumper": "^7.0.5",
83
- "@release-it/conventional-changelog": "^10.0.2",
84
- "@vitest/coverage-v8": "^4.0.14",
85
- "eslint": "9.38.0",
89
+ "@release-it/conventional-changelog": "^10.0.4",
90
+ "@vitest/coverage-v8": "^4.0.16",
91
+ "jsdom": "^27.3.0",
92
+ "eslint": "9.39.2",
86
93
  "fast-glob": "^3.3.3",
87
- "nuxt": "^4.2.1",
94
+ "nuxt": "^4.2.2",
88
95
  "tsx": "^4.21.0",
89
96
  "typescript": "^5.9.3",
90
- "vitest": "^4.0.14",
91
- "vue-tsc": "^3.1.5"
97
+ "vitest": "^4.0.16",
98
+ "vue-tsc": "^3.2.1"
92
99
  }
93
100
  }