@movk/nuxt 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nuxt/movk-ui.css +3 -0
- package/README.md +74 -79
- package/dist/module.d.mts +57 -1
- package/dist/module.json +2 -2
- package/dist/module.mjs +120 -126
- package/dist/runtime/components/AutoForm.d.vue.ts +10 -30
- package/dist/runtime/components/AutoForm.vue +114 -125
- package/dist/runtime/components/AutoForm.vue.d.ts +10 -30
- package/dist/runtime/components/ColorChooser.d.vue.ts +21 -22
- package/dist/runtime/components/ColorChooser.vue +304 -27
- package/dist/runtime/components/ColorChooser.vue.d.ts +21 -22
- package/dist/runtime/components/DataTable.d.vue.ts +57 -0
- package/dist/runtime/components/DataTable.vue +584 -0
- package/dist/runtime/components/DataTable.vue.d.ts +57 -0
- package/dist/runtime/components/DatePicker.d.vue.ts +20 -33
- package/dist/runtime/components/DatePicker.vue +173 -65
- package/dist/runtime/components/DatePicker.vue.d.ts +20 -33
- package/dist/runtime/components/MessageBox.d.vue.ts +36 -0
- package/dist/runtime/components/MessageBox.vue +113 -0
- package/dist/runtime/components/MessageBox.vue.d.ts +36 -0
- package/dist/runtime/components/PillGroup.d.vue.ts +33 -0
- package/dist/runtime/components/PillGroup.vue +291 -0
- package/dist/runtime/components/PillGroup.vue.d.ts +33 -0
- package/dist/runtime/components/Popconfirm.d.vue.ts +30 -0
- package/dist/runtime/components/Popconfirm.vue +143 -0
- package/dist/runtime/components/Popconfirm.vue.d.ts +30 -0
- package/dist/runtime/components/SearchForm.d.vue.ts +21 -149
- package/dist/runtime/components/SearchForm.vue +211 -153
- package/dist/runtime/components/SearchForm.vue.d.ts +21 -149
- package/dist/runtime/components/SlideVerify.d.vue.ts +31 -70
- package/dist/runtime/components/SlideVerify.vue +117 -90
- package/dist/runtime/components/SlideVerify.vue.d.ts +31 -70
- package/dist/runtime/components/StarRating.d.vue.ts +38 -87
- package/dist/runtime/components/StarRating.vue +118 -74
- package/dist/runtime/components/StarRating.vue.d.ts +38 -87
- package/dist/runtime/components/input/AsPhoneNumberInput.d.vue.ts +11 -15
- package/dist/runtime/components/input/AsPhoneNumberInput.vue +22 -9
- package/dist/runtime/components/input/AsPhoneNumberInput.vue.d.ts +11 -15
- package/dist/runtime/components/input/WithCharacterLimit.d.vue.ts +11 -13
- package/dist/runtime/components/input/WithCharacterLimit.vue +23 -11
- package/dist/runtime/components/input/WithCharacterLimit.vue.d.ts +11 -13
- package/dist/runtime/components/input/WithClear.d.vue.ts +13 -11
- package/dist/runtime/components/input/WithClear.vue +27 -8
- package/dist/runtime/components/input/WithClear.vue.d.ts +13 -11
- package/dist/runtime/components/input/WithCopy.d.vue.ts +13 -13
- package/dist/runtime/components/input/WithCopy.vue +25 -8
- package/dist/runtime/components/input/WithCopy.vue.d.ts +13 -13
- package/dist/runtime/components/input/WithFloatingLabel.d.vue.ts +13 -16
- package/dist/runtime/components/input/WithFloatingLabel.vue +35 -27
- package/dist/runtime/components/input/WithFloatingLabel.vue.d.ts +13 -16
- package/dist/runtime/components/input/WithPasswordToggle.d.vue.ts +11 -7
- package/dist/runtime/components/input/WithPasswordToggle.vue +24 -7
- package/dist/runtime/components/input/WithPasswordToggle.vue.d.ts +11 -7
- package/dist/runtime/components/theme-picker/ThemePicker.d.vue.ts +8 -1
- package/dist/runtime/components/theme-picker/ThemePicker.vue +27 -12
- package/dist/runtime/components/theme-picker/ThemePicker.vue.d.ts +8 -1
- package/dist/runtime/components/theme-picker/ThemePickerButton.d.vue.ts +9 -4
- package/dist/runtime/components/theme-picker/ThemePickerButton.vue +4 -0
- package/dist/runtime/components/theme-picker/ThemePickerButton.vue.d.ts +9 -4
- package/dist/runtime/composables/index.d.ts +9 -8
- package/dist/runtime/composables/index.js +1 -0
- package/dist/runtime/composables/useApiFetch.d.ts +10 -5
- package/dist/runtime/composables/useApiFetch.js +20 -2
- package/dist/runtime/composables/useAutoForm.d.ts +4 -4
- package/dist/runtime/composables/useAutoForm.js +23 -9
- package/dist/runtime/composables/useClientApiFetch.d.ts +3 -2
- package/dist/runtime/composables/useDateFormatter.d.ts +16 -3
- package/dist/runtime/composables/useDateFormatter.js +89 -30
- package/dist/runtime/composables/useDownloadWithProgress.d.ts +26 -27
- package/dist/runtime/composables/useDownloadWithProgress.js +142 -40
- package/dist/runtime/composables/useLazyApiFetch.d.ts +3 -2
- package/dist/runtime/composables/useMessageBox.d.ts +6 -0
- package/dist/runtime/composables/useMessageBox.js +16 -0
- package/dist/runtime/composables/useTheme.d.ts +26 -16
- package/dist/runtime/composables/useTheme.js +98 -71
- package/dist/runtime/composables/useUploadWithProgress.d.ts +23 -29
- package/dist/runtime/composables/useUploadWithProgress.js +78 -67
- package/dist/runtime/domains/api/auth.d.ts +2 -0
- package/dist/runtime/domains/api/auth.js +31 -0
- package/dist/runtime/domains/api/endpoint-config.d.ts +11 -0
- package/dist/runtime/domains/api/endpoint-config.js +17 -0
- package/dist/runtime/domains/api/errors.d.ts +2 -0
- package/dist/runtime/domains/api/errors.js +10 -0
- package/dist/runtime/domains/api/fetch-key.d.ts +20 -0
- package/dist/runtime/domains/api/fetch-key.js +23 -0
- package/dist/runtime/domains/api/interceptors/error.d.ts +13 -0
- package/dist/runtime/domains/api/interceptors/error.js +49 -0
- package/dist/runtime/domains/api/interceptors/request.d.ts +12 -0
- package/dist/runtime/domains/api/interceptors/request.js +46 -0
- package/dist/runtime/domains/api/interceptors/response.d.ts +17 -0
- package/dist/runtime/domains/api/interceptors/response.js +27 -0
- package/dist/runtime/domains/api/response.d.ts +4 -0
- package/dist/runtime/domains/api/response.js +14 -0
- package/dist/runtime/domains/api/toast.d.ts +15 -0
- package/dist/runtime/domains/api/toast.js +46 -0
- package/dist/runtime/domains/api/transfer.d.ts +69 -0
- package/dist/runtime/domains/api/transfer.js +81 -0
- package/dist/runtime/domains/auto-form/actions.d.ts +2 -0
- package/dist/runtime/domains/auto-form/actions.js +4 -0
- package/dist/runtime/domains/auto-form/components/Array.d.vue.ts +13 -0
- package/dist/runtime/{components/auto-form-renderer/AutoFormRendererArray.vue → domains/auto-form/components/Array.vue} +25 -29
- package/dist/runtime/domains/auto-form/components/Array.vue.d.ts +13 -0
- package/dist/runtime/domains/auto-form/components/Children.d.vue.ts +11 -0
- package/dist/runtime/{components/auto-form-renderer/AutoFormRendererChildren.vue → domains/auto-form/components/Children.vue} +18 -18
- package/dist/runtime/domains/auto-form/components/Children.vue.d.ts +11 -0
- package/dist/runtime/domains/auto-form/components/Field.d.vue.ts +11 -0
- package/dist/runtime/domains/auto-form/components/Field.vue +56 -0
- package/dist/runtime/domains/auto-form/components/Field.vue.d.ts +11 -0
- package/dist/runtime/domains/auto-form/components/Layout.d.vue.ts +11 -0
- package/dist/runtime/{components/auto-form-renderer/AutoFormRendererLayout.vue → domains/auto-form/components/Layout.vue} +24 -25
- package/dist/runtime/domains/auto-form/components/Layout.vue.d.ts +11 -0
- package/dist/runtime/domains/auto-form/components/Nested.d.vue.ts +11 -0
- package/dist/runtime/{components/auto-form-renderer/AutoFormRendererNested.vue → domains/auto-form/components/Nested.vue} +17 -21
- package/dist/runtime/domains/auto-form/components/Nested.vue.d.ts +11 -0
- package/dist/runtime/domains/auto-form/controls.d.ts +41 -0
- package/dist/runtime/{auto-form → domains/auto-form}/controls.js +27 -24
- package/dist/runtime/{auto-form/field-utils.d.ts → domains/auto-form/fields.d.ts} +3 -1
- package/dist/runtime/{auto-form/field-utils.js → domains/auto-form/fields.js} +18 -2
- package/dist/runtime/{auto-form → domains/auto-form}/metadata.js +1 -1
- package/dist/runtime/domains/auto-form/provider.d.ts +62 -0
- package/dist/runtime/{auto-form → domains/auto-form}/provider.js +6 -3
- package/dist/runtime/{auto-form/reactive-utils.d.ts → domains/auto-form/reactive.d.ts} +5 -5
- package/dist/runtime/{auto-form/reactive-utils.js → domains/auto-form/reactive.js} +1 -1
- package/dist/runtime/{auto-form/schema-introspector.d.ts → domains/auto-form/schema.d.ts} +2 -2
- package/dist/runtime/{auto-form/schema-introspector.js → domains/auto-form/schema.js} +1 -1
- package/dist/runtime/domains/data-table/columns/constants.d.ts +50 -0
- package/dist/runtime/domains/data-table/columns/constants.js +19 -0
- package/dist/runtime/domains/data-table/columns/resolve-columns.d.ts +4 -0
- package/dist/runtime/domains/data-table/columns/resolve-columns.js +59 -0
- package/dist/runtime/domains/data-table/columns/resolve-data-column.d.ts +9 -0
- package/dist/runtime/domains/data-table/columns/resolve-data-column.js +164 -0
- package/dist/runtime/domains/data-table/columns/resolve-group-column.d.ts +4 -0
- package/dist/runtime/domains/data-table/columns/resolve-group-column.js +19 -0
- package/dist/runtime/domains/data-table/columns/resolve-special-columns.d.ts +8 -0
- package/dist/runtime/domains/data-table/columns/resolve-special-columns.js +232 -0
- package/dist/runtime/domains/data-table/columns/style.d.ts +11 -0
- package/dist/runtime/domains/data-table/columns/style.js +67 -0
- package/dist/runtime/domains/data-table/columns/utils.d.ts +6 -0
- package/dist/runtime/domains/data-table/columns/utils.js +16 -0
- package/dist/runtime/domains/data-table/components/ActionConfirm.d.vue.ts +10 -0
- package/dist/runtime/domains/data-table/components/ActionConfirm.vue +39 -0
- package/dist/runtime/domains/data-table/components/ActionConfirm.vue.d.ts +10 -0
- package/dist/runtime/domains/data-table/components/ActionsCell.d.vue.ts +11 -0
- package/dist/runtime/domains/data-table/components/ActionsCell.vue +91 -0
- package/dist/runtime/domains/data-table/components/ActionsCell.vue.d.ts +11 -0
- package/dist/runtime/domains/data-table/components/CellTooltip.d.vue.ts +9 -0
- package/dist/runtime/domains/data-table/components/CellTooltip.vue +40 -0
- package/dist/runtime/domains/data-table/components/CellTooltip.vue.d.ts +9 -0
- package/dist/runtime/domains/data-table/components/Pagination.d.vue.ts +26 -0
- package/dist/runtime/domains/data-table/components/Pagination.vue +132 -0
- package/dist/runtime/domains/data-table/components/Pagination.vue.d.ts +26 -0
- package/dist/runtime/domains/data-table/indent.d.ts +8 -0
- package/dist/runtime/domains/data-table/indent.js +19 -0
- package/dist/runtime/domains/data-table/tree-selection.d.ts +9 -0
- package/dist/runtime/domains/data-table/tree-selection.js +76 -0
- package/dist/runtime/{utils/theme.d.ts → domains/theme/theme-icons.d.ts} +0 -1
- package/dist/runtime/index.css +1 -0
- package/dist/runtime/plugins/api.factory.js +17 -117
- package/dist/runtime/plugins/theme.js +49 -27
- package/dist/runtime/types/api/config.d.ts +127 -0
- package/dist/runtime/types/api/fetch.d.ts +50 -0
- package/dist/runtime/types/api/index.d.ts +5 -0
- package/dist/runtime/types/api/module.d.ts +94 -0
- package/dist/runtime/types/api/response.d.ts +62 -0
- package/dist/runtime/types/api/response.js +0 -0
- package/dist/runtime/types/api/transfer.d.ts +32 -0
- package/dist/runtime/types/api/transfer.js +0 -0
- package/dist/runtime/types/app.config.d.ts +6 -0
- package/dist/runtime/types/auto-form/base.d.ts +26 -0
- package/dist/runtime/types/auto-form/base.js +0 -0
- package/dist/runtime/types/auto-form/component.d.ts +28 -0
- package/dist/runtime/types/auto-form/component.js +0 -0
- package/dist/runtime/types/auto-form/controls.d.ts +45 -0
- package/dist/runtime/types/auto-form/controls.js +0 -0
- package/dist/runtime/types/auto-form/fields.d.ts +68 -0
- package/dist/runtime/types/auto-form/fields.js +0 -0
- package/dist/runtime/types/auto-form/index.d.ts +7 -0
- package/dist/runtime/types/auto-form/index.js +0 -0
- package/dist/runtime/types/auto-form/search-form.d.ts +84 -0
- package/dist/runtime/types/auto-form/search-form.js +0 -0
- package/dist/runtime/types/auto-form/slots.d.ts +85 -0
- package/dist/runtime/types/auto-form/slots.js +0 -0
- package/dist/runtime/types/auto-form/zod-factory.d.ts +127 -0
- package/dist/runtime/types/auto-form/zod-factory.js +0 -0
- package/dist/runtime/types/components/color-chooser.d.ts +109 -0
- package/dist/runtime/types/components/color-chooser.js +0 -0
- package/dist/runtime/types/components/date-picker.d.ts +41 -0
- package/dist/runtime/types/components/date-picker.js +0 -0
- package/dist/runtime/types/components/index.d.ts +8 -0
- package/dist/runtime/types/components/index.js +0 -0
- package/dist/runtime/types/components/input/as-phone-number-input.d.ts +17 -0
- package/dist/runtime/types/components/input/as-phone-number-input.js +0 -0
- package/dist/runtime/types/components/input/index.d.ts +6 -0
- package/dist/runtime/types/components/input/index.js +0 -0
- package/dist/runtime/types/components/input/with-character-limit.d.ts +11 -0
- package/dist/runtime/types/components/input/with-character-limit.js +0 -0
- package/dist/runtime/types/components/input/with-clear.d.ts +10 -0
- package/dist/runtime/types/components/input/with-clear.js +0 -0
- package/dist/runtime/types/components/input/with-copy.d.ts +11 -0
- package/dist/runtime/types/components/input/with-copy.js +0 -0
- package/dist/runtime/types/components/input/with-floating-label.d.ts +12 -0
- package/dist/runtime/types/components/input/with-floating-label.js +0 -0
- package/dist/runtime/types/components/input/with-password-toggle.d.ts +7 -0
- package/dist/runtime/types/components/input/with-password-toggle.js +0 -0
- package/dist/runtime/types/components/message-box.d.ts +69 -0
- package/dist/runtime/types/components/message-box.js +0 -0
- package/dist/runtime/types/components/pill-group.d.ts +103 -0
- package/dist/runtime/types/components/pill-group.js +0 -0
- package/dist/runtime/types/components/popconfirm.d.ts +74 -0
- package/dist/runtime/types/components/popconfirm.js +0 -0
- package/dist/runtime/types/components/slide-verify.d.ts +54 -0
- package/dist/runtime/types/components/slide-verify.js +0 -0
- package/dist/runtime/types/components/star-rating.d.ts +55 -0
- package/dist/runtime/types/components/star-rating.js +0 -0
- package/dist/runtime/types/data-table/columns.d.ts +236 -0
- package/dist/runtime/types/data-table/columns.js +6 -0
- package/dist/runtime/types/data-table/component.d.ts +190 -0
- package/dist/runtime/types/data-table/component.js +0 -0
- package/dist/runtime/types/data-table/contexts.d.ts +44 -0
- package/dist/runtime/types/data-table/contexts.js +0 -0
- package/dist/runtime/types/data-table/index.d.ts +6 -0
- package/dist/runtime/types/data-table/index.js +1 -0
- package/dist/runtime/types/data-table/pagination.d.ts +87 -0
- package/dist/runtime/types/data-table/pagination.js +0 -0
- package/dist/runtime/types/index.d.ts +6 -5
- package/dist/runtime/types/index.js +5 -5
- package/dist/runtime/types/shared.d.ts +5 -0
- package/dist/runtime/types/shared.js +0 -0
- package/dist/runtime/types/zod.d.ts +11 -10
- package/dist/runtime/utils/extend-theme.d.ts +19 -0
- package/dist/runtime/utils/extend-theme.js +44 -0
- package/dist/runtime/utils/form-control.d.ts +33 -0
- package/dist/runtime/utils/form-control.js +54 -0
- package/dist/runtime/utils/meta.d.ts +2 -5
- package/dist/runtime/utils/meta.js +1 -3
- package/dist/runtime/utils/theme-defaults.d.ts +27 -0
- package/dist/runtime/utils/theme-defaults.js +28 -0
- package/dist/runtime/utils/tv.d.ts +1 -0
- package/dist/runtime/utils/tv.js +4 -0
- package/dist/runtime/vue/composables/useSiteConfig.d.ts +13 -0
- package/dist/runtime/vue/composables/useSiteConfig.js +11 -0
- package/dist/runtime/vue/plugins/theme.d.ts +6 -0
- package/dist/runtime/vue/plugins/theme.js +14 -0
- package/dist/runtime/vue/stubs/base.d.ts +2 -0
- package/dist/runtime/vue/stubs/base.js +2 -0
- package/dist/runtime/vue/stubs/inertia.d.ts +2 -0
- package/dist/runtime/vue/stubs/inertia.js +2 -0
- package/dist/runtime/vue/stubs/movk-extra.d.ts +2 -0
- package/dist/runtime/vue/stubs/movk-extra.js +2 -0
- package/dist/runtime/vue/stubs/none.d.ts +2 -0
- package/dist/runtime/vue/stubs/none.js +2 -0
- package/dist/runtime/vue/stubs/vue-router.d.ts +2 -0
- package/dist/runtime/vue/stubs/vue-router.js +2 -0
- package/dist/shared/nuxt.DfBEyjld.mjs +667 -0
- package/dist/types.d.mts +2 -6
- package/dist/unplugin.d.mts +28 -0
- package/dist/unplugin.mjs +292 -0
- package/dist/vite.d.mts +12 -0
- package/dist/vite.mjs +20 -0
- package/package.json +75 -36
- package/vue-plugin.d.ts +5 -0
- package/dist/runtime/auto-form/controls.d.ts +0 -221
- package/dist/runtime/auto-form/provider.d.ts +0 -27
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.d.vue.ts +0 -28
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.vue.d.ts +0 -28
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererChildren.d.vue.ts +0 -26
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererChildren.vue.d.ts +0 -26
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.d.vue.ts +0 -26
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.vue +0 -55
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.vue.d.ts +0 -26
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.d.vue.ts +0 -26
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.vue.d.ts +0 -26
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.d.vue.ts +0 -26
- package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.vue.d.ts +0 -26
- package/dist/runtime/constants/api-defaults.d.ts +0 -9
- package/dist/runtime/constants/api-defaults.js +0 -32
- package/dist/runtime/constants/grid-cols.d.ts +0 -7
- package/dist/runtime/constants/grid-cols.js +0 -44
- package/dist/runtime/style.css +0 -1
- package/dist/runtime/types/api.d.ts +0 -349
- package/dist/runtime/types/auto-form.d.ts +0 -259
- package/dist/runtime/types/module.d.ts +0 -96
- package/dist/runtime/types/theme.d.ts +0 -2
- package/dist/runtime/utils/api-utils.d.ts +0 -58
- package/dist/runtime/utils/api-utils.js +0 -98
- /package/dist/runtime/{constants/auto-form.d.ts → domains/auto-form/constants.d.ts} +0 -0
- /package/dist/runtime/{constants/auto-form.js → domains/auto-form/constants.js} +0 -0
- /package/dist/runtime/{auto-form → domains/auto-form}/metadata.d.ts +0 -0
- /package/dist/runtime/{utils/theme.js → domains/theme/theme-icons.js} +0 -0
- /package/dist/runtime/types/{api.js → api/config.js} +0 -0
- /package/dist/runtime/types/{auto-form.js → api/fetch.js} +0 -0
- /package/dist/runtime/types/{module.js → api/index.js} +0 -0
- /package/dist/runtime/types/{theme.js → api/module.js} +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { simpleHash } from "@movk/core";
|
|
2
|
+
export function buildApiFetchKey(input) {
|
|
3
|
+
const { endpoint, skipUnwrap, skipBusinessCheck, toast, method, url, query, body } = input;
|
|
4
|
+
const payload = {
|
|
5
|
+
e: endpoint ?? null,
|
|
6
|
+
su: skipUnwrap === true,
|
|
7
|
+
sbc: skipBusinessCheck === true,
|
|
8
|
+
t: toast ?? null,
|
|
9
|
+
m: method ?? "GET",
|
|
10
|
+
u: url,
|
|
11
|
+
q: query ?? null,
|
|
12
|
+
b: body ?? null
|
|
13
|
+
};
|
|
14
|
+
let raw;
|
|
15
|
+
try {
|
|
16
|
+
raw = JSON.stringify(payload);
|
|
17
|
+
} catch {
|
|
18
|
+
const toastTag = toast === false ? "off" : toast ? "obj" : "";
|
|
19
|
+
const urlTag = typeof url === "string" ? url : "<req>";
|
|
20
|
+
raw = `${endpoint ?? ""}|${skipUnwrap}|${skipBusinessCheck}|${toastTag}|${payload.m}|${urlTag}|<body>`;
|
|
21
|
+
}
|
|
22
|
+
return `mvk-api:${simpleHash(raw)}`;
|
|
23
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FetchContext } from 'ofetch';
|
|
2
|
+
import type { MovkApiPublicConfig } from '../../../types/api';
|
|
3
|
+
import type { ResolvedEndpointConfig } from '../../../types/api/module';
|
|
4
|
+
import type { useNuxtApp } from '#imports';
|
|
5
|
+
type NuxtApp = ReturnType<typeof useNuxtApp>;
|
|
6
|
+
/**
|
|
7
|
+
* 构造 onResponseError 拦截器
|
|
8
|
+
*
|
|
9
|
+
* @description 401 优先派发 `movk:api:unauthorized` hook 让业务侧自定义处理;
|
|
10
|
+
* `result.handled === true` 时**跳过** `movk:api:error` 派发,避免全局错误上报双计 401。
|
|
11
|
+
*/
|
|
12
|
+
export declare function createOnResponseError(resolvedConfig: ResolvedEndpointConfig, publicConfig: MovkApiPublicConfig, nuxtApp: NuxtApp): (context: FetchContext) => Promise<void>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { navigateTo, useUserSession } from "#imports";
|
|
2
|
+
import { showToast } from "../toast.js";
|
|
3
|
+
function readApiContext(options) {
|
|
4
|
+
return options.context || {};
|
|
5
|
+
}
|
|
6
|
+
async function handleUnauthorized(authConfig, nuxtApp) {
|
|
7
|
+
const unauthorizedConfig = authConfig.unauthorized;
|
|
8
|
+
if (!unauthorizedConfig) return;
|
|
9
|
+
if (unauthorizedConfig.clearSession) {
|
|
10
|
+
try {
|
|
11
|
+
const userSession = nuxtApp.vueApp.runWithContext(() => useUserSession());
|
|
12
|
+
if (userSession?.clear) {
|
|
13
|
+
await userSession.clear();
|
|
14
|
+
await userSession.fetch();
|
|
15
|
+
}
|
|
16
|
+
} catch {
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (unauthorizedConfig.redirect) {
|
|
20
|
+
const loginPath = unauthorizedConfig.loginPath || "/login";
|
|
21
|
+
await nuxtApp.runWithContext(() => navigateTo(loginPath));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function createOnResponseError(resolvedConfig, publicConfig, nuxtApp) {
|
|
25
|
+
const { auth: authConfig, toast: toastConfig, response: responseConfig } = resolvedConfig;
|
|
26
|
+
return async function onResponseError(context) {
|
|
27
|
+
const { response } = context;
|
|
28
|
+
if (!response) return;
|
|
29
|
+
const { toast } = readApiContext(context.options);
|
|
30
|
+
let unauthorizedHandled = false;
|
|
31
|
+
if (response.status === 401) {
|
|
32
|
+
const result = { handled: false };
|
|
33
|
+
await nuxtApp.callHook("movk:api:unauthorized", context, result);
|
|
34
|
+
unauthorizedHandled = result.handled;
|
|
35
|
+
if (!unauthorizedHandled) {
|
|
36
|
+
await handleUnauthorized(authConfig, nuxtApp);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!unauthorizedHandled) {
|
|
40
|
+
await nuxtApp.callHook("movk:api:error", context);
|
|
41
|
+
}
|
|
42
|
+
const data = response._data;
|
|
43
|
+
const fallback = `\u8BF7\u6C42\u5931\u8D25 (${response.status})`;
|
|
44
|
+
showToast("error", data ?? fallback, toast, toastConfig, responseConfig);
|
|
45
|
+
if (publicConfig.debug) {
|
|
46
|
+
console.error("[@movk/nuxt] Error:", response.status, response._data);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FetchContext } from 'ofetch';
|
|
2
|
+
import type { MovkApiPublicConfig } from '../../../types/api';
|
|
3
|
+
import type { ResolvedEndpointConfig } from '../../../types/api/module';
|
|
4
|
+
import type { useNuxtApp } from '#imports';
|
|
5
|
+
type NuxtApp = ReturnType<typeof useNuxtApp>;
|
|
6
|
+
/**
|
|
7
|
+
* 构造 onRequest 拦截器:注入认证头、debug 日志、派发 movk:api:request hook
|
|
8
|
+
*
|
|
9
|
+
* @description Headers 重建前会过滤 undefined 值,规避 ofetch 某些版本 `Record<string, string | undefined>` 导致的 TypeError
|
|
10
|
+
*/
|
|
11
|
+
export declare function createOnRequest(resolvedConfig: ResolvedEndpointConfig, publicConfig: MovkApiPublicConfig, nuxtApp: NuxtApp): (context: FetchContext) => Promise<void>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { getAuthHeaders } from "../auth.js";
|
|
2
|
+
function toHeaderRecord(headers) {
|
|
3
|
+
const out = {};
|
|
4
|
+
if (!headers) return out;
|
|
5
|
+
if (headers instanceof Headers) {
|
|
6
|
+
headers.forEach((value, key) => {
|
|
7
|
+
out[key] = value;
|
|
8
|
+
});
|
|
9
|
+
return out;
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(headers)) {
|
|
12
|
+
for (const entry of headers) {
|
|
13
|
+
if (entry && entry[1] !== void 0) out[entry[0]] = entry[1];
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
18
|
+
if (value !== void 0) out[key] = value;
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
export function createOnRequest(resolvedConfig, publicConfig, nuxtApp) {
|
|
23
|
+
const { auth: authConfig } = resolvedConfig;
|
|
24
|
+
return async function onRequest(context) {
|
|
25
|
+
if (authConfig.enabled) {
|
|
26
|
+
const authHeaders = getAuthHeaders(authConfig);
|
|
27
|
+
const normalized = toHeaderRecord(context.options.headers);
|
|
28
|
+
const headers = new Headers(normalized);
|
|
29
|
+
for (const [key, value] of Object.entries(authHeaders)) {
|
|
30
|
+
headers.set(key, value);
|
|
31
|
+
}
|
|
32
|
+
context.options.headers = headers;
|
|
33
|
+
}
|
|
34
|
+
if (publicConfig.debug) {
|
|
35
|
+
const h = context.options.headers;
|
|
36
|
+
const headersLog = h instanceof Headers ? Object.fromEntries(h.entries()) : h;
|
|
37
|
+
console.info("[@movk/nuxt] Request:", {
|
|
38
|
+
method: context.options.method || "GET",
|
|
39
|
+
url: `${resolvedConfig.baseURL}${context.request}`,
|
|
40
|
+
headers: headersLog,
|
|
41
|
+
body: context.options.body ? "(body present)" : void 0
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
await nuxtApp.callHook("movk:api:request", context);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FetchContext } from 'ofetch';
|
|
2
|
+
import type { MovkApiPublicConfig } from '../../../types/api';
|
|
3
|
+
import type { ResolvedEndpointConfig } from '../../../types/api/module';
|
|
4
|
+
import type { useNuxtApp } from '#imports';
|
|
5
|
+
type NuxtApp = ReturnType<typeof useNuxtApp>;
|
|
6
|
+
/**
|
|
7
|
+
* 构造 onResponse 拦截器
|
|
8
|
+
*
|
|
9
|
+
* @description 业务校验链路:
|
|
10
|
+
* - 校验通过(或 skipBusinessCheck)→ 按 skipUnwrap 决定是否解包 _data → 派发 movk:api:response hook → 触发成功 toast
|
|
11
|
+
* - 校验失败 → 派发 movk:api:error hook → 触发错误 toast → 抛 createApiError
|
|
12
|
+
*
|
|
13
|
+
* **契约**:拦截器输出 = 业务数据。`movk:api:response` hook 收到的 `context.response._data` 已解包;
|
|
14
|
+
* 调用方设置 `skipUnwrap: true` 时不重写 `_data`,保留原始响应。
|
|
15
|
+
*/
|
|
16
|
+
export declare function createOnResponse(resolvedConfig: ResolvedEndpointConfig, publicConfig: MovkApiPublicConfig, nuxtApp: NuxtApp): (context: FetchContext) => Promise<void>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { extractData, extractMessage, isBusinessSuccess } from "../response.js";
|
|
2
|
+
import { createApiError } from "../errors.js";
|
|
3
|
+
import { showToast } from "../toast.js";
|
|
4
|
+
function readApiContext(options) {
|
|
5
|
+
return options.context || {};
|
|
6
|
+
}
|
|
7
|
+
export function createOnResponse(resolvedConfig, publicConfig, nuxtApp) {
|
|
8
|
+
const { toast: toastConfig, response: responseConfig } = resolvedConfig;
|
|
9
|
+
return async function onResponse(context) {
|
|
10
|
+
const raw = context.response?._data;
|
|
11
|
+
const { toast, skipBusinessCheck, skipUnwrap } = readApiContext(context.options);
|
|
12
|
+
if (publicConfig.debug) {
|
|
13
|
+
console.info("[@movk/nuxt] Response:", raw);
|
|
14
|
+
}
|
|
15
|
+
if (skipBusinessCheck || isBusinessSuccess(raw, responseConfig)) {
|
|
16
|
+
if (!skipUnwrap && context.response) {
|
|
17
|
+
context.response._data = extractData(raw, responseConfig);
|
|
18
|
+
}
|
|
19
|
+
await nuxtApp.callHook("movk:api:response", context);
|
|
20
|
+
showToast("success", raw, toast, toastConfig, responseConfig);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
await nuxtApp.callHook("movk:api:error", context);
|
|
24
|
+
showToast("error", raw, toast, toastConfig, responseConfig);
|
|
25
|
+
throw createApiError(raw, extractMessage(raw, responseConfig));
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ApiResponse, ApiResponseConfig } from '../../types/api';
|
|
2
|
+
export declare function isBusinessSuccess(response: ApiResponse, config?: Partial<ApiResponseConfig>): boolean;
|
|
3
|
+
export declare function extractMessage(response: ApiResponse, config?: Partial<ApiResponseConfig>): string | undefined;
|
|
4
|
+
export declare function extractData(response: ApiResponse, config?: Partial<ApiResponseConfig>): unknown;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function isBusinessSuccess(response, config = {}) {
|
|
2
|
+
const codeKey = config.codeKey || "code";
|
|
3
|
+
const successCodes = config.successCodes || [200, 0];
|
|
4
|
+
const code = response[codeKey];
|
|
5
|
+
return successCodes.includes(code);
|
|
6
|
+
}
|
|
7
|
+
export function extractMessage(response, config = {}) {
|
|
8
|
+
const messageKey = config.messageKey || "message";
|
|
9
|
+
return response[messageKey] || response.message || response.msg;
|
|
10
|
+
}
|
|
11
|
+
export function extractData(response, config = {}) {
|
|
12
|
+
const dataKey = config.dataKey || "data";
|
|
13
|
+
return dataKey in response ? response[dataKey] : void 0;
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ApiResponse, ApiResponseConfig, ApiToastConfig, RequestToastOptions } from '../../types/api';
|
|
2
|
+
type ToastType = 'success' | 'error';
|
|
3
|
+
/**
|
|
4
|
+
* 触发 Toast 提示
|
|
5
|
+
*
|
|
6
|
+
* @description 决策收敛在本函数内:是否启用 / 类型是否启用 / 提示文案选择 / payload 构造。
|
|
7
|
+
*
|
|
8
|
+
* @param type 提示类型
|
|
9
|
+
* @param source 字符串作为 fallback 文案;ApiResponse 时按 responseConfig 抽取 message;undefined 走类型默认文案
|
|
10
|
+
* @param requestOptions 单次请求覆盖配置;为 false 时整体禁用
|
|
11
|
+
* @param globalConfig 全局 Toast 配置(已合并端点级覆盖)
|
|
12
|
+
* @param responseConfig 用于从 ApiResponse 抽取 message 的字段映射;source 为字符串时可省略
|
|
13
|
+
*/
|
|
14
|
+
export declare function showToast(type: ToastType, source: ApiResponse | string | undefined, requestOptions: RequestToastOptions | false | undefined, globalConfig: Partial<ApiToastConfig>, responseConfig?: Partial<ApiResponseConfig>): void;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { extractMessage } from "./response.js";
|
|
2
|
+
import { useNuxtApp, useToast } from "#imports";
|
|
3
|
+
function getToast() {
|
|
4
|
+
try {
|
|
5
|
+
const nuxtApp = useNuxtApp();
|
|
6
|
+
return nuxtApp.vueApp.runWithContext(() => useToast());
|
|
7
|
+
} catch {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function pickMessage(type, source, requestOptions, responseConfig) {
|
|
12
|
+
if (typeof requestOptions === "object") {
|
|
13
|
+
const custom = requestOptions[`${type}Message`];
|
|
14
|
+
if (custom) return custom;
|
|
15
|
+
}
|
|
16
|
+
if (typeof source === "string") return source;
|
|
17
|
+
if (source && responseConfig) {
|
|
18
|
+
const extracted = extractMessage(source, responseConfig);
|
|
19
|
+
if (extracted) return extracted;
|
|
20
|
+
}
|
|
21
|
+
return type === "success" ? "\u64CD\u4F5C\u6210\u529F" : "\u8BF7\u6C42\u5931\u8D25";
|
|
22
|
+
}
|
|
23
|
+
function compact(obj) {
|
|
24
|
+
const out = {};
|
|
25
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
26
|
+
if (v !== void 0) out[k] = v;
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
export function showToast(type, source, requestOptions, globalConfig, responseConfig) {
|
|
31
|
+
if (globalConfig.enabled === false || requestOptions === false) return;
|
|
32
|
+
const typeConfig = globalConfig[type];
|
|
33
|
+
if (typeConfig?.show === false) return;
|
|
34
|
+
if (requestOptions?.[type] === false) return;
|
|
35
|
+
const message = pickMessage(type, source, requestOptions, responseConfig);
|
|
36
|
+
if (!message) return;
|
|
37
|
+
const toast = getToast();
|
|
38
|
+
if (!toast) return;
|
|
39
|
+
const { show: _show, ...typeConfigProps } = typeConfig ?? {};
|
|
40
|
+
const requestTypeConfig = typeof requestOptions?.[type] === "object" ? requestOptions[type] : {};
|
|
41
|
+
toast.add(compact({
|
|
42
|
+
title: message,
|
|
43
|
+
...typeConfigProps,
|
|
44
|
+
...requestTypeConfig
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { FetchContext, FetchOptions } from 'ofetch';
|
|
2
|
+
import type { ApiResponse, MovkApiPublicConfig, RequestToastOptions, TransferRequestOptions, TransferResult } from '../../types/api';
|
|
3
|
+
import type { ResolvedEndpointConfig } from '../../types/api/module';
|
|
4
|
+
import type { useNuxtApp } from '#imports';
|
|
5
|
+
type NuxtApp = ReturnType<typeof useNuxtApp>;
|
|
6
|
+
/**
|
|
7
|
+
* 预备传输上下文
|
|
8
|
+
*/
|
|
9
|
+
export interface PreparedTransfer {
|
|
10
|
+
fullUrl: string;
|
|
11
|
+
headers: Record<string, string>;
|
|
12
|
+
config: ResolvedEndpointConfig;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 解析端点 + 拼装 URL + 合并 headers(auth 在前、用户在后,用户优先)
|
|
16
|
+
*/
|
|
17
|
+
export declare function prepareTransfer(publicConfig: MovkApiPublicConfig, url: string, options: TransferRequestOptions): PreparedTransfer;
|
|
18
|
+
/**
|
|
19
|
+
* 解析下载文件名
|
|
20
|
+
* @description 优先级:override > content-disposition > URL pathname 末段 > 'download'
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveFilename(headers: Headers, url: string, override?: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* 安全解析 JSON 响应
|
|
25
|
+
* @description content-type 含 application/json 时尝试 JSON.parse;失败或非 JSON 返回 null
|
|
26
|
+
*/
|
|
27
|
+
export declare function tryParseJsonResponse(headers: Headers, text: string): ApiResponse | null;
|
|
28
|
+
/**
|
|
29
|
+
* 把 XHR 的 getAllResponseHeaders() 字符串解析为标准 Headers
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseXhrHeaders(raw: string): Headers;
|
|
32
|
+
/**
|
|
33
|
+
* finalizeTransfer 入参
|
|
34
|
+
*/
|
|
35
|
+
export interface FinalizeTransferContext<T> {
|
|
36
|
+
/** JSON 响应体;纯二进制成功时为 null */
|
|
37
|
+
raw: ApiResponse | null;
|
|
38
|
+
/** 无 JSON 时由调用方提供成功/失败判定与默认数据 */
|
|
39
|
+
fallback?: {
|
|
40
|
+
isSuccess: boolean;
|
|
41
|
+
data: T | null;
|
|
42
|
+
message?: string;
|
|
43
|
+
};
|
|
44
|
+
config: ResolvedEndpointConfig;
|
|
45
|
+
publicConfig: MovkApiPublicConfig;
|
|
46
|
+
/** 单次请求 toast 覆盖;false 整体禁用 */
|
|
47
|
+
requestToast: RequestToastOptions | false | undefined;
|
|
48
|
+
skipBusinessCheck?: boolean;
|
|
49
|
+
/** 合成的 FetchContext,用于派发 movk:api:* hook */
|
|
50
|
+
fetchContext: FetchContext;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 统一处理传输结果:业务校验 → 派发 hook → 触发 toast → 构造 TransferResult
|
|
54
|
+
*
|
|
55
|
+
* @description 本函数**不抛异常**,所有错误以 result.error 形式返回,由 composable 自行决定是否 throw。
|
|
56
|
+
* 中止场景应由调用方在调用本函数前短路,不要进入此函数。
|
|
57
|
+
*/
|
|
58
|
+
export declare function finalizeTransfer<T>(nuxtApp: NuxtApp, ctx: FinalizeTransferContext<T>): Promise<TransferResult<T>>;
|
|
59
|
+
/**
|
|
60
|
+
* 合成一个最小可用的 FetchContext,供 hook 订阅者使用
|
|
61
|
+
*
|
|
62
|
+
* @description 由于上传/下载基于 XHR / fetch,不经 ofetch;此处提供必要字段以与 $api 的 hook 契约对齐。
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildFetchContext(request: string, options: FetchOptions, response?: {
|
|
65
|
+
status: number;
|
|
66
|
+
headers: Headers;
|
|
67
|
+
_data?: unknown;
|
|
68
|
+
}): FetchContext;
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { extractFilename } from "@movk/core";
|
|
2
|
+
import { getAuthHeaders } from "./auth.js";
|
|
3
|
+
import { resolveEndpointConfig } from "./endpoint-config.js";
|
|
4
|
+
import { createApiError } from "./errors.js";
|
|
5
|
+
import { extractData, extractMessage, isBusinessSuccess } from "./response.js";
|
|
6
|
+
import { showToast } from "./toast.js";
|
|
7
|
+
export function prepareTransfer(publicConfig, url, options) {
|
|
8
|
+
const config = resolveEndpointConfig(publicConfig, options.endpoint);
|
|
9
|
+
const fullUrl = `${config.baseURL || ""}${url}`;
|
|
10
|
+
const authHeaders = getAuthHeaders(config.auth);
|
|
11
|
+
const headers = { ...authHeaders, ...options.headers || {} };
|
|
12
|
+
return { fullUrl, headers, config };
|
|
13
|
+
}
|
|
14
|
+
export function resolveFilename(headers, url, override) {
|
|
15
|
+
if (override) return override;
|
|
16
|
+
const fromHeader = extractFilename(headers, "");
|
|
17
|
+
if (fromHeader) return fromHeader;
|
|
18
|
+
try {
|
|
19
|
+
const base = typeof location !== "undefined" ? location.origin : "http://localhost";
|
|
20
|
+
const pathname = new URL(url, base).pathname;
|
|
21
|
+
const last = pathname.split("/").filter(Boolean).pop();
|
|
22
|
+
if (last) return last;
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
25
|
+
return "download";
|
|
26
|
+
}
|
|
27
|
+
export function tryParseJsonResponse(headers, text) {
|
|
28
|
+
const contentType = headers.get("content-type") || "";
|
|
29
|
+
if (!contentType.toLowerCase().includes("application/json")) return null;
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(text);
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function parseXhrHeaders(raw) {
|
|
37
|
+
const headers = new Headers();
|
|
38
|
+
if (!raw) return headers;
|
|
39
|
+
for (const line of raw.trim().split(/\r?\n/)) {
|
|
40
|
+
const idx = line.indexOf(":");
|
|
41
|
+
if (idx <= 0) continue;
|
|
42
|
+
const name = line.slice(0, idx).trim();
|
|
43
|
+
const value = line.slice(idx + 1).trim();
|
|
44
|
+
if (name) headers.append(name, value);
|
|
45
|
+
}
|
|
46
|
+
return headers;
|
|
47
|
+
}
|
|
48
|
+
export async function finalizeTransfer(nuxtApp, ctx) {
|
|
49
|
+
const { raw, fallback, config, publicConfig, requestToast, skipBusinessCheck, fetchContext } = ctx;
|
|
50
|
+
const { response: responseConfig, toast: toastConfig } = config;
|
|
51
|
+
if (publicConfig.debug) {
|
|
52
|
+
console.info("[@movk/nuxt] Transfer response:", raw ?? fallback);
|
|
53
|
+
}
|
|
54
|
+
const hasRaw = raw !== null;
|
|
55
|
+
const isSuccess = hasRaw ? skipBusinessCheck || isBusinessSuccess(raw, responseConfig) : fallback?.isSuccess ?? false;
|
|
56
|
+
if (isSuccess) {
|
|
57
|
+
const data = hasRaw ? skipBusinessCheck ? raw : extractData(raw, responseConfig) : fallback?.data ?? null;
|
|
58
|
+
if (fetchContext.response) {
|
|
59
|
+
fetchContext.response._data = data;
|
|
60
|
+
}
|
|
61
|
+
await nuxtApp.callHook("movk:api:response", fetchContext);
|
|
62
|
+
showToast("success", raw ?? fallback?.message, requestToast, toastConfig, responseConfig);
|
|
63
|
+
return { data, error: null, aborted: false };
|
|
64
|
+
}
|
|
65
|
+
const message = hasRaw ? extractMessage(raw, responseConfig) || fallback?.message : fallback?.message;
|
|
66
|
+
const apiError = hasRaw ? createApiError(raw, message) : Object.assign(new Error(message || "\u8BF7\u6C42\u5931\u8D25"), { isBusinessError: false });
|
|
67
|
+
if (fetchContext.response) {
|
|
68
|
+
fetchContext.response._data = raw ?? void 0;
|
|
69
|
+
}
|
|
70
|
+
fetchContext.error = apiError;
|
|
71
|
+
await nuxtApp.callHook("movk:api:error", fetchContext);
|
|
72
|
+
showToast("error", raw ?? message, requestToast, toastConfig, responseConfig);
|
|
73
|
+
return { data: null, error: apiError, aborted: false };
|
|
74
|
+
}
|
|
75
|
+
export function buildFetchContext(request, options, response) {
|
|
76
|
+
return {
|
|
77
|
+
request,
|
|
78
|
+
options,
|
|
79
|
+
response
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { ButtonProps } from '@nuxt/ui';
|
|
3
|
+
import type { AutoFormField } from '../../../types/auto-form';
|
|
4
|
+
import type { AnyObject } from '@movk/core';
|
|
5
|
+
interface AutoFormRendererArrayProps {
|
|
6
|
+
schema: z.ZodObject;
|
|
7
|
+
field: AutoFormField;
|
|
8
|
+
extraProps?: AnyObject;
|
|
9
|
+
addButtonProps?: Partial<ButtonProps>;
|
|
10
|
+
}
|
|
11
|
+
declare const __VLS_export: import("vue").DefineComponent<AutoFormRendererArrayProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<AutoFormRendererArrayProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -1,28 +1,23 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { UButton, UCollapsible } from "#components";
|
|
3
3
|
import { computed, ref } from "vue";
|
|
4
|
-
import { useAutoFormInjector } from "
|
|
4
|
+
import { useAutoFormInjector } from "../provider";
|
|
5
5
|
import { joinPath } from "@movk/core";
|
|
6
|
-
import { collectFieldDefaults, createHintSlotFactory } from "
|
|
7
|
-
import { VNodeRender } from "
|
|
8
|
-
import AutoFormRendererField from "./
|
|
9
|
-
import AutoFormRendererNested from "./
|
|
10
|
-
const {
|
|
11
|
-
|
|
12
|
-
field,
|
|
13
|
-
schema,
|
|
14
|
-
addButtonProps: customAddButtonProps
|
|
15
|
-
} = defineProps({
|
|
6
|
+
import { collectFieldDefaults, createHintSlotFactory } from "../fields";
|
|
7
|
+
import { VNodeRender } from "../reactive";
|
|
8
|
+
import AutoFormRendererField from "./Field.vue";
|
|
9
|
+
import AutoFormRendererNested from "./Nested.vue";
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
schema: { type: null, required: true },
|
|
16
12
|
field: { type: Object, required: true },
|
|
17
13
|
extraProps: { type: Object, required: false },
|
|
18
|
-
addButtonProps: { type: Object, required: false }
|
|
19
|
-
schema: { type: null, required: false }
|
|
14
|
+
addButtonProps: { type: Object, required: false }
|
|
20
15
|
});
|
|
21
|
-
const { createCollapsibleEnhancer, createFieldContext, createSlotResolver, createSlotProps } = useAutoFormInjector();
|
|
22
|
-
const context = createFieldContext(field);
|
|
23
|
-
const slotResolver = computed(() => createSlotResolver(field, extraProps));
|
|
24
|
-
const slotProps = computed(() => createSlotProps(field, extraProps));
|
|
25
|
-
const elementTemplate = computed(() => field.arrayElement);
|
|
16
|
+
const { createCollapsibleEnhancer, createFieldContext, createSlotResolver, createSlotProps, resolveFieldProp } = useAutoFormInjector();
|
|
17
|
+
const context = createFieldContext(props.field);
|
|
18
|
+
const slotResolver = computed(() => createSlotResolver(props.field, props.extraProps));
|
|
19
|
+
const slotProps = computed(() => createSlotProps(props.field, props.extraProps));
|
|
20
|
+
const elementTemplate = computed(() => props.field.arrayElement);
|
|
26
21
|
const isObjectElement = computed(() => elementTemplate.value?.meta.type === "object");
|
|
27
22
|
const arrayValue = computed(() => {
|
|
28
23
|
const value = context.value;
|
|
@@ -33,7 +28,7 @@ const idCounter = ref(0);
|
|
|
33
28
|
function ensureItemIds() {
|
|
34
29
|
const arr = arrayValue.value;
|
|
35
30
|
while (itemIds.value.length < arr.length) {
|
|
36
|
-
itemIds.value.push(`${field.path}-${idCounter.value++}`);
|
|
31
|
+
itemIds.value.push(`${props.field.path}-${idCounter.value++}`);
|
|
37
32
|
}
|
|
38
33
|
}
|
|
39
34
|
function getItemId(_item, index) {
|
|
@@ -52,7 +47,7 @@ function updateFieldPaths(template, oldBasePath, newBasePath, hintSlotFactory) {
|
|
|
52
47
|
fieldSlots: isNested && !isObject ? {
|
|
53
48
|
...template.meta?.fieldSlots
|
|
54
49
|
} : {
|
|
55
|
-
hint: (
|
|
50
|
+
hint: (props2) => hintSlotFactory(template, props2.path, props2.open, props2.count),
|
|
56
51
|
...template.meta?.fieldSlots
|
|
57
52
|
}
|
|
58
53
|
}
|
|
@@ -71,8 +66,8 @@ const arrayItemFields = computed(() => {
|
|
|
71
66
|
return [];
|
|
72
67
|
const factory = createHintSlotFactory(removeItem);
|
|
73
68
|
return arr.map((_, index) => {
|
|
74
|
-
const newBasePath = joinPath([field.path, index]);
|
|
75
|
-
return updateFieldPaths(template, field.path, newBasePath, factory);
|
|
69
|
+
const newBasePath = joinPath([props.field.path, index]);
|
|
70
|
+
return updateFieldPaths(template, props.field.path, newBasePath, factory);
|
|
76
71
|
});
|
|
77
72
|
});
|
|
78
73
|
function createDefaultValue() {
|
|
@@ -93,7 +88,7 @@ function removeItem(count) {
|
|
|
93
88
|
itemIds.value = [...itemIds.value.slice(0, count), ...itemIds.value.slice(count + 1)];
|
|
94
89
|
context.setValue(newArray);
|
|
95
90
|
}
|
|
96
|
-
const { collapsibleConfig, shouldShowCollapsible, isHidden, enhancedField } = createCollapsibleEnhancer(field, extraProps);
|
|
91
|
+
const { collapsibleConfig, shouldShowCollapsible, isHidden, enhancedField } = createCollapsibleEnhancer(props.field, props.extraProps);
|
|
97
92
|
const DEFAULT_ADD_BUTTON_PROPS = {
|
|
98
93
|
icon: "i-lucide-plus",
|
|
99
94
|
color: "info",
|
|
@@ -102,14 +97,15 @@ const DEFAULT_ADD_BUTTON_PROPS = {
|
|
|
102
97
|
};
|
|
103
98
|
const addButtonProps = computed(() => ({
|
|
104
99
|
...DEFAULT_ADD_BUTTON_PROPS,
|
|
105
|
-
|
|
100
|
+
size: resolveFieldProp(props.field, "size", "sm", props.extraProps),
|
|
101
|
+
...props.addButtonProps
|
|
106
102
|
}));
|
|
107
103
|
</script>
|
|
108
104
|
|
|
109
105
|
<template>
|
|
110
106
|
<UCollapsible v-if="shouldShowCollapsible" v-show="!isHidden" v-bind="collapsibleConfig || {}">
|
|
111
107
|
<template #default="{ open }">
|
|
112
|
-
<AutoFormRendererField :field="enhancedField" :schema="schema" :extra-props="{ ...extraProps, open }" />
|
|
108
|
+
<AutoFormRendererField :field="enhancedField" :schema="props.schema" :extra-props="{ ...props.extraProps, open }" />
|
|
113
109
|
</template>
|
|
114
110
|
|
|
115
111
|
<template v-if="elementTemplate" #content>
|
|
@@ -120,8 +116,8 @@ const addButtonProps = computed(() => ({
|
|
|
120
116
|
<component
|
|
121
117
|
:is="isObjectElement ? AutoFormRendererNested : AutoFormRendererField"
|
|
122
118
|
:field="itemField"
|
|
123
|
-
:schema="schema"
|
|
124
|
-
:extra-props="{ ...extraProps, count }"
|
|
119
|
+
:schema="props.schema"
|
|
120
|
+
:extra-props="{ ...props.extraProps, count }"
|
|
125
121
|
/>
|
|
126
122
|
</template>
|
|
127
123
|
</template>
|
|
@@ -137,8 +133,8 @@ const addButtonProps = computed(() => ({
|
|
|
137
133
|
<component
|
|
138
134
|
:is="isObjectElement ? AutoFormRendererNested : AutoFormRendererField"
|
|
139
135
|
:field="itemField"
|
|
140
|
-
:schema="schema"
|
|
141
|
-
:extra-props="{ ...extraProps, count }"
|
|
136
|
+
:schema="props.schema"
|
|
137
|
+
:extra-props="{ ...props.extraProps, count }"
|
|
142
138
|
/>
|
|
143
139
|
</template>
|
|
144
140
|
<UButton v-bind="addButtonProps" @click="addItem">
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { ButtonProps } from '@nuxt/ui';
|
|
3
|
+
import type { AutoFormField } from '../../../types/auto-form';
|
|
4
|
+
import type { AnyObject } from '@movk/core';
|
|
5
|
+
interface AutoFormRendererArrayProps {
|
|
6
|
+
schema: z.ZodObject;
|
|
7
|
+
field: AutoFormField;
|
|
8
|
+
extraProps?: AnyObject;
|
|
9
|
+
addButtonProps?: Partial<ButtonProps>;
|
|
10
|
+
}
|
|
11
|
+
declare const __VLS_export: import("vue").DefineComponent<AutoFormRendererArrayProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<AutoFormRendererArrayProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { AutoFormField } from '../../../types/auto-form';
|
|
3
|
+
import type { AnyObject } from '@movk/core';
|
|
4
|
+
interface AutoFormRendererChildrenProps {
|
|
5
|
+
schema: z.ZodObject;
|
|
6
|
+
fields: AutoFormField[];
|
|
7
|
+
extraProps?: AnyObject;
|
|
8
|
+
}
|
|
9
|
+
declare const __VLS_export: import("vue").DefineComponent<AutoFormRendererChildrenProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<AutoFormRendererChildrenProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|