@aithe/aithe-ui 26.2.3 → 26.3.2
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 +19 -11
- package/dist/apps/admin/app.js +12 -0
- package/dist/apps/admin/components/admin-app.js +83 -0
- package/dist/apps/admin/components/admin-layout.d.ts +0 -1
- package/dist/apps/admin/components/admin-layout.d.ts.map +1 -1
- package/dist/apps/admin/components/admin-layout.js +250 -0
- package/dist/apps/admin/datahub/auth.js +24 -0
- package/dist/apps/admin/datahub/dashboard.js +16 -0
- package/dist/apps/admin/datahub/index.js +42 -0
- package/dist/apps/admin/datahub/menu.js +16 -0
- package/dist/apps/admin/datahub/mock/auth.js +11 -0
- package/dist/apps/admin/datahub/mock/dashboard.js +10 -0
- package/dist/apps/admin/datahub/mock/menu.js +42 -0
- package/dist/apps/admin/i18n/de-DE.js +37 -0
- package/dist/apps/admin/i18n/en-US.js +37 -0
- package/dist/apps/admin/i18n/es-ES.js +38 -0
- package/dist/apps/admin/i18n/fr-FR.js +37 -0
- package/dist/apps/admin/i18n/index.js +27 -0
- package/dist/apps/admin/i18n/ja-JP.js +38 -0
- package/dist/apps/admin/i18n/ko-KR.js +37 -0
- package/dist/apps/admin/i18n/pt-BR.js +37 -0
- package/dist/apps/admin/i18n/zh-CN.js +37 -0
- package/dist/apps/admin/i18n/zh-HK.js +37 -0
- package/dist/apps/admin/i18n/zh-TW.js +37 -0
- package/dist/apps/admin/pages/dashboard-page.d.ts +1 -0
- package/dist/apps/admin/pages/dashboard-page.d.ts.map +1 -1
- package/dist/apps/admin/pages/dashboard-page.js +199 -0
- package/dist/apps/admin/pages/login-page.js +278 -0
- package/dist/apps/admin/pages/not-found-page.js +57 -0
- package/dist/apps/admin/pages/role-page.js +76 -0
- package/dist/apps/admin/pages/settings-page.js +95 -0
- package/dist/apps/admin/pages/user-page.js +76 -0
- package/dist/apps/admin/router/index.js +43 -0
- package/dist/apps/admin/standalone.js +1 -0
- package/dist/apps/admin/store/auth.js +42 -0
- package/dist/apps/api/app.js +82 -0
- package/dist/apps/api/demo-data.d.ts.map +1 -1
- package/dist/apps/api/demo-data.js +965 -0
- package/dist/apps/api/docs-viewer.js +684 -0
- package/dist/apps/api/i18n/de-DE.d.ts.map +1 -1
- package/dist/apps/api/i18n/de-DE.js +131 -0
- package/dist/apps/api/i18n/en-US.d.ts.map +1 -1
- package/dist/apps/api/i18n/en-US.js +141 -0
- package/dist/apps/api/i18n/es-ES.d.ts.map +1 -1
- package/dist/apps/api/i18n/es-ES.js +131 -0
- package/dist/apps/api/i18n/fr-FR.d.ts.map +1 -1
- package/dist/apps/api/i18n/fr-FR.js +131 -0
- package/dist/apps/api/i18n/index.js +27 -0
- package/dist/apps/api/i18n/ja-JP.d.ts.map +1 -1
- package/dist/apps/api/i18n/ja-JP.js +131 -0
- package/dist/apps/api/i18n/ko-KR.d.ts.map +1 -1
- package/dist/apps/api/i18n/ko-KR.js +131 -0
- package/dist/apps/api/i18n/pt-BR.d.ts.map +1 -1
- package/dist/apps/api/i18n/pt-BR.js +131 -0
- package/dist/apps/api/i18n/zh-CN.d.ts.map +1 -1
- package/dist/apps/api/i18n/zh-CN.js +141 -0
- package/dist/apps/api/i18n/zh-HK.d.ts.map +1 -1
- package/dist/apps/api/i18n/zh-HK.js +131 -0
- package/dist/apps/api/i18n/zh-TW.d.ts.map +1 -1
- package/dist/apps/api/i18n/zh-TW.js +131 -0
- package/dist/apps/api/pages/docs.d.ts.map +1 -1
- package/dist/apps/api/pages/docs.js +369 -0
- package/dist/apps/api/standalone.js +1 -0
- package/dist/apps/demo/app.d.ts.map +1 -1
- package/dist/apps/demo/app.js +275 -0
- package/dist/apps/demo/editor.d.ts.map +1 -1
- package/dist/apps/demo/editor.js +270 -0
- package/dist/apps/demo/helpers.js +7 -0
- package/dist/apps/demo/i18n/de-DE.d.ts.map +1 -1
- package/dist/apps/demo/i18n/de-DE.js +289 -0
- package/dist/apps/demo/i18n/en-US.d.ts.map +1 -1
- package/dist/apps/demo/i18n/en-US.js +301 -0
- package/dist/apps/demo/i18n/es-ES.d.ts.map +1 -1
- package/dist/apps/demo/i18n/es-ES.js +289 -0
- package/dist/apps/demo/i18n/fr-FR.d.ts.map +1 -1
- package/dist/apps/demo/i18n/fr-FR.js +289 -0
- package/dist/apps/demo/i18n/index.js +27 -0
- package/dist/apps/demo/i18n/ja-JP.d.ts.map +1 -1
- package/dist/apps/demo/i18n/ja-JP.js +289 -0
- package/dist/apps/demo/i18n/ko-KR.d.ts.map +1 -1
- package/dist/apps/demo/i18n/ko-KR.js +289 -0
- package/dist/apps/demo/i18n/pt-BR.d.ts.map +1 -1
- package/dist/apps/demo/i18n/pt-BR.js +289 -0
- package/dist/apps/demo/i18n/zh-CN.d.ts.map +1 -1
- package/dist/apps/demo/i18n/zh-CN.js +301 -0
- package/dist/apps/demo/i18n/zh-HK.d.ts.map +1 -1
- package/dist/apps/demo/i18n/zh-HK.js +289 -0
- package/dist/apps/demo/i18n/zh-TW.d.ts.map +1 -1
- package/dist/apps/demo/i18n/zh-TW.js +289 -0
- package/dist/apps/demo/pages/autoform.d.ts.map +1 -1
- package/dist/apps/demo/pages/autoform.js +422 -0
- package/dist/apps/demo/pages/autoview.d.ts +3 -0
- package/dist/apps/demo/pages/autoview.d.ts.map +1 -0
- package/dist/apps/demo/pages/autoview.js +310 -0
- package/dist/apps/demo/pages/basic.js +157 -0
- package/dist/apps/demo/pages/code.js +1088 -0
- package/dist/apps/demo/pages/container.js +42 -0
- package/dist/apps/demo/pages/dashboard.js +159 -0
- package/dist/apps/demo/pages/data.d.ts.map +1 -1
- package/dist/apps/demo/pages/data.js +327 -0
- package/dist/apps/demo/pages/display.d.ts.map +1 -1
- package/dist/apps/demo/pages/display.js +295 -0
- package/dist/apps/demo/pages/feedback.js +94 -0
- package/dist/apps/demo/pages/form.d.ts.map +1 -1
- package/dist/apps/demo/pages/form.js +119 -0
- package/dist/apps/demo/pages/layout.js +74 -0
- package/dist/apps/demo/pages/navigation.js +54 -0
- package/dist/apps/demo/pages/progress.js +42 -0
- package/dist/apps/demo/pages/theme.js +126 -0
- package/dist/apps/demo/standalone.js +1 -0
- package/dist/components/basic/AGENTS.md +1 -0
- package/dist/components/basic/avatar.js +168 -0
- package/dist/components/basic/badge.js +157 -0
- package/dist/components/basic/button-group.js +70 -0
- package/dist/components/basic/button.d.ts +2 -4
- package/dist/components/basic/button.d.ts.map +1 -1
- package/dist/components/basic/button.js +315 -0
- package/dist/components/basic/card.js +186 -0
- package/dist/components/basic/chip.js +103 -0
- package/dist/components/basic/divider.js +127 -0
- package/dist/components/basic/empty.js +72 -0
- package/dist/components/basic/icon.js +129 -0
- package/dist/components/basic/input.d.ts.map +1 -1
- package/dist/components/basic/input.js +314 -0
- package/dist/components/basic/tag.d.ts +7 -2
- package/dist/components/basic/tag.d.ts.map +1 -1
- package/dist/components/basic/tag.js +248 -0
- package/dist/components/basic/textarea.d.ts +0 -1
- package/dist/components/basic/textarea.d.ts.map +1 -1
- package/dist/components/basic/textarea.js +130 -0
- package/dist/components/container/callout.js +108 -0
- package/dist/components/container/details.js +117 -0
- package/dist/components/container/scroller.js +144 -0
- package/dist/components/container/split-panel.js +150 -0
- package/dist/components/data/AGENTS.md +1 -1
- package/dist/components/data/box-table.d.ts +53 -0
- package/dist/components/data/box-table.d.ts.map +1 -0
- package/dist/components/data/box-table.js +220 -0
- package/dist/components/data/dropdown.d.ts +8 -5
- package/dist/components/data/dropdown.d.ts.map +1 -1
- package/dist/components/data/dropdown.js +219 -0
- package/dist/components/data/metrics-group.js +180 -0
- package/dist/components/data/metrics.d.ts +11 -0
- package/dist/components/data/metrics.d.ts.map +1 -1
- package/dist/components/data/metrics.js +309 -0
- package/dist/components/data/pagination.js +119 -0
- package/dist/components/data/tab-pane.d.ts +58 -12
- package/dist/components/data/tab-pane.d.ts.map +1 -1
- package/dist/components/data/tab-pane.js +130 -0
- package/dist/components/data/table-column.d.ts +29 -5
- package/dist/components/data/table-column.d.ts.map +1 -1
- package/dist/components/data/table-column.js +123 -0
- package/dist/components/data/table.d.ts +134 -54
- package/dist/components/data/table.d.ts.map +1 -1
- package/dist/components/data/table.js +1210 -0
- package/dist/components/data/tabs.d.ts +60 -3
- package/dist/components/data/tabs.d.ts.map +1 -1
- package/dist/components/data/tabs.js +416 -0
- package/dist/components/data/timeline-item.js +127 -0
- package/dist/components/data/timeline.js +204 -0
- package/dist/components/data/tree-menu.d.ts +12 -2
- package/dist/components/data/tree-menu.d.ts.map +1 -1
- package/dist/components/data/tree-menu.js +482 -0
- package/dist/components/data/tree.js +269 -0
- package/dist/components/display/AGENTS.md +5 -2
- package/dist/components/display/animated-image.js +98 -0
- package/dist/components/display/autoview.d.ts +139 -0
- package/dist/components/display/autoview.d.ts.map +1 -0
- package/dist/components/display/autoview.js +460 -0
- package/dist/components/display/brief-box.d.ts +42 -0
- package/dist/components/display/brief-box.d.ts.map +1 -0
- package/dist/components/display/brief-box.js +117 -0
- package/dist/components/display/carousel.js +223 -0
- package/dist/components/display/code-editor.d.ts.map +1 -1
- package/dist/components/display/code-editor.js +976 -0
- package/dist/components/display/comparison.js +132 -0
- package/dist/components/display/desc-item.d.ts +48 -0
- package/dist/components/display/desc-item.d.ts.map +1 -0
- package/dist/components/display/desc-item.js +150 -0
- package/dist/components/display/desc.d.ts +68 -0
- package/dist/components/display/desc.d.ts.map +1 -0
- package/dist/components/display/desc.js +405 -0
- package/dist/components/display/detail-box.d.ts +51 -0
- package/dist/components/display/detail-box.d.ts.map +1 -0
- package/dist/components/display/detail-box.js +157 -0
- package/dist/components/display/label.js +166 -0
- package/dist/components/display/markdown-editor.js +319 -0
- package/dist/components/display/markdown.d.ts.map +1 -1
- package/dist/components/display/markdown.js +193 -0
- package/dist/components/display/mini-box.d.ts +31 -0
- package/dist/components/display/mini-box.d.ts.map +1 -0
- package/dist/components/display/mini-box.js +137 -0
- package/dist/components/display/profile.d.ts +18 -0
- package/dist/components/display/profile.d.ts.map +1 -0
- package/dist/components/display/profile.js +164 -0
- package/dist/components/feedback/AGENTS.md +1 -0
- package/dist/components/feedback/alert.js +150 -0
- package/dist/components/feedback/dialog.js +228 -0
- package/dist/components/feedback/drawer.d.ts.map +1 -1
- package/dist/components/feedback/drawer.js +338 -0
- package/dist/components/feedback/loading.js +130 -0
- package/dist/components/feedback/modal.d.ts.map +1 -1
- package/dist/components/feedback/modal.js +303 -0
- package/dist/components/feedback/notification.js +170 -0
- package/dist/components/feedback/popover.d.ts +1 -1
- package/dist/components/feedback/popover.js +124 -0
- package/dist/components/feedback/toast.js +142 -0
- package/dist/components/feedback/tooltip.d.ts +1 -1
- package/dist/components/feedback/tooltip.js +153 -0
- package/dist/components/form/AGENTS.md +4 -0
- package/dist/components/form/autoform-item.d.ts +6 -0
- package/dist/components/form/autoform-item.d.ts.map +1 -1
- package/dist/components/form/autoform-item.js +791 -0
- package/dist/components/form/autoform.d.ts +15 -5
- package/dist/components/form/autoform.d.ts.map +1 -1
- package/dist/components/form/autoform.js +303 -0
- package/dist/components/form/checkbox-group.js +118 -0
- package/dist/components/form/checkbox.js +123 -0
- package/dist/components/form/color-picker.js +148 -0
- package/dist/components/form/combobox.d.ts +4 -0
- package/dist/components/form/combobox.d.ts.map +1 -1
- package/dist/components/form/combobox.js +325 -0
- package/dist/components/form/date-picker.js +123 -0
- package/dist/components/form/form-item.d.ts.map +1 -1
- package/dist/components/form/form-item.js +141 -0
- package/dist/components/form/form.js +94 -0
- package/dist/components/form/radio-group.js +106 -0
- package/dist/components/form/radio.js +110 -0
- package/dist/components/form/rate.js +116 -0
- package/dist/components/form/select.d.ts +5 -1
- package/dist/components/form/select.d.ts.map +1 -1
- package/dist/components/form/select.js +539 -0
- package/dist/components/form/slider.js +134 -0
- package/dist/components/form/switch.js +146 -0
- package/dist/components/form/time-picker.js +92 -0
- package/dist/components/form/transfer.js +273 -0
- package/dist/components/form/upload.js +138 -0
- package/dist/components/framework/body.js +333 -0
- package/dist/components/framework/dashboard-panel.js +519 -0
- package/dist/components/framework/dashboard.d.ts.map +1 -1
- package/dist/components/framework/dashboard.js +1084 -0
- package/dist/components/framework/header.js +237 -0
- package/dist/components/framework/log-panel.js +637 -0
- package/dist/components/framework/page.js +151 -0
- package/dist/components/framework/sidebar.d.ts +4 -10
- package/dist/components/framework/sidebar.d.ts.map +1 -1
- package/dist/components/framework/sidebar.js +477 -0
- package/dist/components/layout/affix.js +137 -0
- package/dist/components/layout/col.js +103 -0
- package/dist/components/layout/collapse-item.js +165 -0
- package/dist/components/layout/collapse.js +108 -0
- package/dist/components/layout/container.js +92 -0
- package/dist/components/layout/flex.js +100 -0
- package/dist/components/layout/row.js +103 -0
- package/dist/components/layout/space.js +85 -0
- package/dist/components/navigation/back-top.js +127 -0
- package/dist/components/navigation/breadcrumb-item.js +108 -0
- package/dist/components/navigation/breadcrumb.js +70 -0
- package/dist/components/navigation/menu-item.js +181 -0
- package/dist/components/navigation/menu.js +126 -0
- package/dist/components/navigation/steps.js +183 -0
- package/dist/components/navigation/sub-menu.d.ts.map +1 -1
- package/dist/components/navigation/sub-menu.js +252 -0
- package/dist/components/progress/progress-bar.js +97 -0
- package/dist/components/progress/progress-ring.js +111 -0
- package/dist/components/progress/skeleton.js +108 -0
- package/dist/components/progress/spinner.js +129 -0
- package/dist/components/theme/locale-switch.js +241 -0
- package/dist/components/theme/shadow-picker.js +233 -0
- package/dist/components/theme/shape-picker.js +232 -0
- package/dist/components/theme/theme-picker.js +236 -0
- package/dist/components/theme/theme-preview.d.ts +1 -2
- package/dist/components/theme/theme-preview.d.ts.map +1 -1
- package/dist/components/theme/theme-preview.js +376 -0
- package/dist/components/theme/theme-switch.d.ts.map +1 -1
- package/dist/components/theme/theme-switch.js +318 -0
- package/dist/components/theme/typo-picker.js +219 -0
- package/dist/core/AGENTS.md +6 -1
- package/dist/core/aithe-element.d.ts +2 -2
- package/dist/core/aithe-element.js +135 -0
- package/dist/core/aithe-widget.js +30 -0
- package/dist/core/anchored-overlay.d.ts +3 -0
- package/dist/core/anchored-overlay.d.ts.map +1 -1
- package/dist/core/anchored-overlay.js +111 -0
- package/dist/core/autoform/autoform.js +79 -0
- package/dist/core/autoform/autoview.d.ts +86 -0
- package/dist/core/autoform/autoview.d.ts.map +1 -0
- package/dist/core/autoform/autoview.js +37 -0
- package/dist/core/autoform/condition.js +170 -0
- package/dist/core/autoform/index.d.ts +2 -0
- package/dist/core/autoform/index.d.ts.map +1 -1
- package/dist/core/autoform/index.js +9 -0
- package/dist/core/autoform/types.js +7 -0
- package/dist/core/datahub/__tests__/force-options.test.d.ts +8 -0
- package/dist/core/datahub/__tests__/force-options.test.d.ts.map +1 -0
- package/dist/core/datahub/__tests__/force-options.test.js +161 -0
- package/dist/core/datahub/config/strategy.d.ts +1 -1
- package/dist/core/datahub/config/strategy.d.ts.map +1 -1
- package/dist/core/datahub/config/strategy.js +50 -0
- package/dist/core/datahub/core/adapter/fetch-adapter.d.ts +1 -1
- package/dist/core/datahub/core/adapter/fetch-adapter.d.ts.map +1 -1
- package/dist/core/datahub/core/adapter/fetch-adapter.js +118 -0
- package/dist/core/datahub/core/adapter/index.js +7 -0
- package/dist/core/datahub/core/adapter/mock-adapter.d.ts +1 -1
- package/dist/core/datahub/core/adapter/mock-adapter.d.ts.map +1 -1
- package/dist/core/datahub/core/adapter/mock-adapter.js +58 -0
- package/dist/core/datahub/core/api-styles.d.ts +1 -1
- package/dist/core/datahub/core/api-styles.d.ts.map +1 -1
- package/dist/core/datahub/core/api-styles.js +136 -0
- package/dist/core/datahub/core/datahub-core.d.ts +53 -3
- package/dist/core/datahub/core/datahub-core.d.ts.map +1 -1
- package/dist/core/datahub/core/datahub-core.js +520 -0
- package/dist/core/datahub/core/index.js +7 -0
- package/dist/core/datahub/index.js +50 -0
- package/dist/core/datahub/types.d.ts +24 -0
- package/dist/core/datahub/types.d.ts.map +1 -1
- package/dist/core/datahub/types.js +31 -0
- package/dist/core/datahub/utils/cache.js +55 -0
- package/dist/core/datahub/utils/common.js +23 -0
- package/dist/core/datahub/utils/dedup.d.ts +1 -1
- package/dist/core/datahub/utils/dedup.d.ts.map +1 -1
- package/dist/core/datahub/utils/dedup.js +52 -0
- package/dist/core/datahub/utils/idempotent.js +61 -0
- package/dist/core/datahub/utils/is-query.js +53 -0
- package/dist/core/datahub/utils/loading.js +78 -0
- package/dist/core/filter/__tests__/index.test.d.ts +2 -0
- package/dist/core/filter/__tests__/index.test.d.ts.map +1 -0
- package/dist/core/filter/__tests__/index.test.js +230 -0
- package/dist/core/filter/builtins.d.ts +60 -0
- package/dist/core/filter/builtins.d.ts.map +1 -0
- package/dist/core/filter/builtins.js +172 -0
- package/dist/core/filter/factory.d.ts +54 -0
- package/dist/core/filter/factory.d.ts.map +1 -0
- package/dist/core/filter/factory.js +96 -0
- package/dist/core/filter/index.d.ts +11 -0
- package/dist/core/filter/index.d.ts.map +1 -0
- package/dist/core/filter/index.js +9 -0
- package/dist/core/filter/types.d.ts +12 -0
- package/dist/core/filter/types.d.ts.map +1 -0
- package/dist/core/filter/types.js +1 -0
- package/dist/core/floating.js +132 -0
- package/dist/core/highlight/index.js +43 -0
- package/dist/core/highlight/lang-bash.js +27 -0
- package/dist/core/highlight/lang-c.js +27 -0
- package/dist/core/highlight/lang-cmake.js +27 -0
- package/dist/core/highlight/lang-cpp.js +27 -0
- package/dist/core/highlight/lang-css.js +24 -0
- package/dist/core/highlight/lang-dart.js +27 -0
- package/dist/core/highlight/lang-dockerfile.js +16 -0
- package/dist/core/highlight/lang-fsharp.js +23 -0
- package/dist/core/highlight/lang-go.js +22 -0
- package/dist/core/highlight/lang-html.js +12 -0
- package/dist/core/highlight/lang-java.js +22 -0
- package/dist/core/highlight/lang-javascript.js +26 -0
- package/dist/core/highlight/lang-json.js +13 -0
- package/dist/core/highlight/lang-jsonline.js +13 -0
- package/dist/core/highlight/lang-jsx.js +30 -0
- package/dist/core/highlight/lang-kotlin.js +27 -0
- package/dist/core/highlight/lang-latex.js +22 -0
- package/dist/core/highlight/lang-lua.js +26 -0
- package/dist/core/highlight/lang-makefile.js +22 -0
- package/dist/core/highlight/lang-markdown.js +18 -0
- package/dist/core/highlight/lang-objectivec.js +24 -0
- package/dist/core/highlight/lang-perl.js +30 -0
- package/dist/core/highlight/lang-powershell.js +23 -0
- package/dist/core/highlight/lang-python.js +27 -0
- package/dist/core/highlight/lang-r.js +21 -0
- package/dist/core/highlight/lang-ruby.js +29 -0
- package/dist/core/highlight/lang-rust.js +24 -0
- package/dist/core/highlight/lang-scala.js +26 -0
- package/dist/core/highlight/lang-sql.js +21 -0
- package/dist/core/highlight/lang-svelte.js +27 -0
- package/dist/core/highlight/lang-swift.js +28 -0
- package/dist/core/highlight/lang-tsx.js +35 -0
- package/dist/core/highlight/lang-typescript.js +31 -0
- package/dist/core/highlight/lang-vue.js +29 -0
- package/dist/core/highlight/lang-wasm.js +22 -0
- package/dist/core/highlight/lang-xml.js +12 -0
- package/dist/core/highlight/lang-yaml.js +14 -0
- package/dist/core/highlight/registry.js +99 -0
- package/dist/core/logger/LoggerCore.js +626 -0
- package/dist/core/logger/index.js +10 -0
- package/dist/core/logger/types.js +29 -0
- package/dist/core/markdown/index.js +20 -0
- package/dist/core/markdown/parser.d.ts +2 -0
- package/dist/core/markdown/parser.d.ts.map +1 -1
- package/dist/core/markdown/parser.js +376 -0
- package/dist/core/markdown/plugins.d.ts +2 -1
- package/dist/core/markdown/plugins.d.ts.map +1 -1
- package/dist/core/markdown/plugins.js +755 -0
- package/dist/core/markdown/types.d.ts +5 -0
- package/dist/core/markdown/types.d.ts.map +1 -1
- package/dist/core/markdown/types.js +7 -0
- package/dist/core/router/index.js +244 -0
- package/dist/core/styles.js +44 -0
- package/dist/core/types.d.ts +52 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3695 -1622
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +1844 -758
- package/dist/index.umd.js.map +1 -1
- package/dist/styles/aithe-ui.d.ts +23 -0
- package/dist/styles/aithe-ui.d.ts.map +1 -1
- package/dist/styles/aithe-ui.js +185 -0
- package/dist/styles/global.css.d.ts +1 -1
- package/dist/styles/global.css.d.ts.map +1 -1
- package/dist/styles/global.css.js +119 -0
- package/dist/styles/i18n/index.js +206 -0
- package/dist/styles/i18n/locales/de-DE.d.ts.map +1 -1
- package/dist/styles/i18n/locales/de-DE.js +151 -0
- package/dist/styles/i18n/locales/en-US.d.ts.map +1 -1
- package/dist/styles/i18n/locales/en-US.js +160 -0
- package/dist/styles/i18n/locales/es-ES.d.ts.map +1 -1
- package/dist/styles/i18n/locales/es-ES.js +151 -0
- package/dist/styles/i18n/locales/fr-FR.d.ts.map +1 -1
- package/dist/styles/i18n/locales/fr-FR.js +151 -0
- package/dist/styles/i18n/locales/index.js +14 -0
- package/dist/styles/i18n/locales/ja-JP.d.ts.map +1 -1
- package/dist/styles/i18n/locales/ja-JP.js +151 -0
- package/dist/styles/i18n/locales/ko-KR.d.ts.map +1 -1
- package/dist/styles/i18n/locales/ko-KR.js +151 -0
- package/dist/styles/i18n/locales/pt-BR.d.ts.map +1 -1
- package/dist/styles/i18n/locales/pt-BR.js +151 -0
- package/dist/styles/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/styles/i18n/locales/zh-CN.js +160 -0
- package/dist/styles/i18n/locales/zh-HK.d.ts.map +1 -1
- package/dist/styles/i18n/locales/zh-HK.js +151 -0
- package/dist/styles/i18n/locales/zh-TW.d.ts.map +1 -1
- package/dist/styles/i18n/locales/zh-TW.js +151 -0
- package/dist/styles/layout/index.js +88 -0
- package/dist/styles/mixins.js +43 -0
- package/dist/styles/shadow/cyber.js +19 -0
- package/dist/styles/shadow/deep.js +19 -0
- package/dist/styles/shadow/diffuse.js +19 -0
- package/dist/styles/shadow/flat.js +19 -0
- package/dist/styles/shadow/glassmorphism.js +19 -0
- package/dist/styles/shadow/index.js +129 -0
- package/dist/styles/shadow/neumorphism.js +21 -0
- package/dist/styles/shadow/retro.js +19 -0
- package/dist/styles/shadow/sharp-business.js +19 -0
- package/dist/styles/shadow/skeuomorphic.js +21 -0
- package/dist/styles/shape/chamfer.js +19 -0
- package/dist/styles/shape/circle.js +19 -0
- package/dist/styles/shape/index.js +174 -0
- package/dist/styles/shape/organic.js +19 -0
- package/dist/styles/shape/pill.js +19 -0
- package/dist/styles/shape/rounded.js +21 -0
- package/dist/styles/shape/rounder.js +19 -0
- package/dist/styles/shape/sharp.js +19 -0
- package/dist/styles/shape/smooth.js +19 -0
- package/dist/styles/theme/aliyun.d.ts +1 -1
- package/dist/styles/theme/aliyun.d.ts.map +1 -1
- package/dist/styles/theme/aliyun.js +102 -0
- package/dist/styles/theme/amber.d.ts +1 -1
- package/dist/styles/theme/amber.d.ts.map +1 -1
- package/dist/styles/theme/amber.js +101 -0
- package/dist/styles/theme/blue.d.ts +1 -1
- package/dist/styles/theme/blue.d.ts.map +1 -1
- package/dist/styles/theme/blue.js +101 -0
- package/dist/styles/theme/charcoal.d.ts +1 -1
- package/dist/styles/theme/charcoal.d.ts.map +1 -1
- package/dist/styles/theme/charcoal.js +106 -0
- package/dist/styles/theme/cyan.d.ts +1 -1
- package/dist/styles/theme/cyan.d.ts.map +1 -1
- package/dist/styles/theme/cyan.js +96 -0
- package/dist/styles/theme/dark.d.ts +1 -1
- package/dist/styles/theme/dark.d.ts.map +1 -1
- package/dist/styles/theme/dark.js +106 -0
- package/dist/styles/theme/ebony.d.ts +1 -1
- package/dist/styles/theme/ebony.d.ts.map +1 -1
- package/dist/styles/theme/ebony.js +106 -0
- package/dist/styles/theme/festive.d.ts +1 -1
- package/dist/styles/theme/festive.d.ts.map +1 -1
- package/dist/styles/theme/festive.js +101 -0
- package/dist/styles/theme/graphite.d.ts +1 -1
- package/dist/styles/theme/graphite.d.ts.map +1 -1
- package/dist/styles/theme/graphite.js +106 -0
- package/dist/styles/theme/gray.d.ts +1 -1
- package/dist/styles/theme/gray.d.ts.map +1 -1
- package/dist/styles/theme/gray.js +101 -0
- package/dist/styles/theme/huawei.d.ts +1 -1
- package/dist/styles/theme/huawei.d.ts.map +1 -1
- package/dist/styles/theme/huawei.js +102 -0
- package/dist/styles/theme/index.d.ts +1 -1
- package/dist/styles/theme/index.d.ts.map +1 -1
- package/dist/styles/theme/index.js +276 -0
- package/dist/styles/theme/indigo.d.ts +1 -1
- package/dist/styles/theme/indigo.d.ts.map +1 -1
- package/dist/styles/theme/indigo.js +101 -0
- package/dist/styles/theme/ink.d.ts +1 -1
- package/dist/styles/theme/ink.d.ts.map +1 -1
- package/dist/styles/theme/ink.js +106 -0
- package/dist/styles/theme/light.d.ts +1 -1
- package/dist/styles/theme/light.d.ts.map +1 -1
- package/dist/styles/theme/light.js +102 -0
- package/dist/styles/theme/midnight.d.ts +1 -1
- package/dist/styles/theme/midnight.d.ts.map +1 -1
- package/dist/styles/theme/midnight.js +106 -0
- package/dist/styles/theme/navy.d.ts +1 -1
- package/dist/styles/theme/navy.d.ts.map +1 -1
- package/dist/styles/theme/navy.js +106 -0
- package/dist/styles/theme/obsidian.d.ts +1 -1
- package/dist/styles/theme/obsidian.d.ts.map +1 -1
- package/dist/styles/theme/obsidian.js +106 -0
- package/dist/styles/theme/onyx.d.ts +1 -1
- package/dist/styles/theme/onyx.d.ts.map +1 -1
- package/dist/styles/theme/onyx.js +106 -0
- package/dist/styles/theme/orange.d.ts +1 -1
- package/dist/styles/theme/orange.d.ts.map +1 -1
- package/dist/styles/theme/orange.js +101 -0
- package/dist/styles/theme/pink.d.ts +1 -1
- package/dist/styles/theme/pink.d.ts.map +1 -1
- package/dist/styles/theme/pink.js +101 -0
- package/dist/styles/theme/purple.d.ts +1 -1
- package/dist/styles/theme/purple.d.ts.map +1 -1
- package/dist/styles/theme/purple.js +101 -0
- package/dist/styles/theme/raisin.d.ts +1 -1
- package/dist/styles/theme/raisin.d.ts.map +1 -1
- package/dist/styles/theme/raisin.js +106 -0
- package/dist/styles/theme/slate.d.ts +1 -1
- package/dist/styles/theme/slate.d.ts.map +1 -1
- package/dist/styles/theme/slate.js +106 -0
- package/dist/styles/theme/teal.d.ts +1 -1
- package/dist/styles/theme/teal.d.ts.map +1 -1
- package/dist/styles/theme/teal.js +101 -0
- package/dist/styles/theme/tianyi.d.ts +1 -1
- package/dist/styles/theme/tianyi.d.ts.map +1 -1
- package/dist/styles/theme/tianyi.js +102 -0
- package/dist/styles/types.js +1 -0
- package/dist/styles/typo/business.js +34 -0
- package/dist/styles/typo/compact.js +34 -0
- package/dist/styles/typo/index.js +99 -0
- package/dist/styles/typo/luxury.js +34 -0
- package/dist/styles/typo/minimal.js +34 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/dom.js +51 -0
- package/dist/utils/events.js +32 -0
- package/dist/utils/icon.js +176 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/utils.d.ts +5 -5
- package/dist/utils/utils.js +89 -0
- package/dist/utils/validation.js +52 -0
- package/docs/api/basic/button.md +9 -6
- package/docs/api/basic/tag.md +24 -17
- package/docs/api/data/box-table.md +73 -0
- package/docs/api/data/dropdown.md +3 -2
- package/docs/api/data/metrics.md +2 -0
- package/docs/api/data/table-column.md +37 -23
- package/docs/api/data/table.md +158 -44
- package/docs/api/data/tabs.md +46 -1
- package/docs/api/data/tree-menu.md +55 -2
- package/docs/api/display/autoview.md +277 -0
- package/docs/api/display/box.md +66 -0
- package/docs/api/display/brief-box.md +73 -0
- package/docs/api/display/desc-item.md +57 -0
- package/docs/api/display/desc.md +246 -0
- package/docs/api/display/detail-box.md +75 -0
- package/docs/api/display/mini-box.md +100 -0
- package/docs/api/display/profile.md +92 -0
- package/docs/api/feedback/popover.md +10 -10
- package/docs/api/feedback/tooltip.md +14 -14
- package/docs/api/form/autoform-item.md +115 -0
- package/docs/api/form/autoform.md +7 -3
- package/docs/api/form/combobox.md +27 -7
- package/docs/api/form/select.md +50 -28
- package/docs/api/framework/log-panel.md +46 -0
- package/docs/api/framework/sidebar.md +3 -2
- package/docs/api/summary.md +46 -35
- package/docs/api/theme/theme-switch.md +1 -1
- package/docs/autoform.md +14 -33
- package/docs/changelog/CHANGELOG.md +155 -0
- package/docs/changelog/VERSION_26.3.1.md +966 -0
- package/docs/changelog/VERSION_26.3.2.md +852 -0
- package/docs/datahub.md +4 -1
- package/docs/filter.md +332 -0
- package/docs/framework-integration.md +2 -2
- package/docs/guide.md +72 -6
- package/docs/i18n.md +2 -4
- package/docs/issue/26.3.1/issue_26.3.1.0.md +84 -0
- package/docs/issue/26.3.1/issue_26.3.1.1.md +72 -0
- package/docs/issue/26.3.1/issue_26.3.1.2.md +75 -0
- package/docs/issue/26.3.1/issue_26.3.1.3.md +78 -0
- package/docs/issue/26.3.1/issue_26.3.1.4.md +113 -0
- package/docs/issue/26.3.1/issue_26.3.1.5.md +142 -0
- package/docs/issue/26.3.1/issue_26.3.1.6.md +100 -0
- package/docs/issue/26.3.1/issue_26.3.1.7.md +78 -0
- package/docs/issue/26.3.2/issue_26.3.2.1.md +46 -0
- package/docs/issue/26.3.2/issue_26.3.2.2.md +82 -0
- package/docs/issue/26.3.2/issue_26.3.2.3.md +57 -0
- package/docs/issue/26.3.2/issue_26.3.2.4.md +43 -0
- package/docs/issue/AGENTS.md +24 -3
- package/docs/markdown.md +2 -2
- package/docs/quickstart.md +5 -5
- package/docs/theming.md +5 -4
- package/package.json +5 -2
- package/dist/components/navigation/dropdown.d.ts +0 -56
- package/dist/components/navigation/dropdown.d.ts.map +0 -1
- /package/docs/issue/{issue_26.2.2.1.md → 26.2.2/issue_26.2.2.1.md} +0 -0
- /package/docs/issue/{issue_26.2.2.2.md → 26.2.2/issue_26.2.2.2.md} +0 -0
- /package/docs/issue/{issue_26.2.2.3.md → 26.2.2/issue_26.2.2.3.md} +0 -0
- /package/docs/issue/{issue_26.2.2.4.md → 26.2.2/issue_26.2.2.4.md} +0 -0
- /package/docs/issue/{issue_26.2.3.1.md → 26.2.3/issue_26.2.3.1.md} +0 -0
- /package/docs/issue/{issue_26.2.3.10.md → 26.2.3/issue_26.2.3.10.md} +0 -0
- /package/docs/issue/{issue_26.2.3.11.md → 26.2.3/issue_26.2.3.11.md} +0 -0
- /package/docs/issue/{issue_26.2.3.12.md → 26.2.3/issue_26.2.3.12.md} +0 -0
- /package/docs/issue/{issue_26.2.3.13.md → 26.2.3/issue_26.2.3.13.md} +0 -0
- /package/docs/issue/{issue_26.2.3.14.md → 26.2.3/issue_26.2.3.14.md} +0 -0
- /package/docs/issue/{issue_26.2.3.15.md → 26.2.3/issue_26.2.3.15.md} +0 -0
- /package/docs/issue/{issue_26.2.3.16.md → 26.2.3/issue_26.2.3.16.md} +0 -0
- /package/docs/issue/{issue_26.2.3.2.md → 26.2.3/issue_26.2.3.2.md} +0 -0
- /package/docs/issue/{issue_26.2.3.3.md → 26.2.3/issue_26.2.3.3.md} +0 -0
- /package/docs/issue/{issue_26.2.3.4.md → 26.2.3/issue_26.2.3.4.md} +0 -0
- /package/docs/issue/{issue_26.2.3.5.md → 26.2.3/issue_26.2.3.5.md} +0 -0
- /package/docs/issue/{issue_26.2.3.6.md → 26.2.3/issue_26.2.3.6.md} +0 -0
- /package/docs/issue/{issue_26.2.3.7.md → 26.2.3/issue_26.2.3.7.md} +0 -0
- /package/docs/issue/{issue_26.2.3.8.md → 26.2.3/issue_26.2.3.8.md} +0 -0
- /package/docs/issue/{issue_26.2.3.9.md → 26.2.3/issue_26.2.3.9.md} +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file DataHub 类型定义 / DataHub Type Definitions
|
|
3
|
+
* @description 定义 DataHub 数据中间层的所有标准类型,包括 APIStyle 业务协议相关类型。
|
|
4
|
+
*
|
|
5
|
+
* 核心设计原则:
|
|
6
|
+
* - DataHub 只负责 HTTP 传输层(请求/响应),不关心业务协议
|
|
7
|
+
* - 业务协议(如 code/message/data 结构)由 APIStyle 封装
|
|
8
|
+
* - 适配器只做 JSON 解析,不做业务语义判断
|
|
9
|
+
*
|
|
10
|
+
* Defines all standard types for the DataHub middleware layer,
|
|
11
|
+
* including APIStyle business protocol types.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* DataHub 统一错误类 / DataHub Unified Error Class
|
|
15
|
+
* @description 封装网络错误、中断错误、HTTP 错误等,提供统一的错误结构。
|
|
16
|
+
* 包含错误码、链路追踪 ID、HTTP 状态码和请求 URL 等信息。
|
|
17
|
+
* Encapsulates network errors, abort errors, HTTP errors, etc.,
|
|
18
|
+
* providing a unified error structure with error code, trace ID,
|
|
19
|
+
* HTTP status code, and request URL.
|
|
20
|
+
*/
|
|
21
|
+
export class DataHubError extends Error {
|
|
22
|
+
constructor(detail) {
|
|
23
|
+
super(detail.message);
|
|
24
|
+
this.name = 'DataHubError';
|
|
25
|
+
this.code = detail.code;
|
|
26
|
+
this.trace = detail.trace;
|
|
27
|
+
this.status = detail.status;
|
|
28
|
+
this.url = detail.url;
|
|
29
|
+
this.data = detail.data;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file 内存缓存工具 / In-Memory Cache Utility
|
|
3
|
+
* @description 为查询类请求提供基于 TTL(Time-To-Live)的内存缓存。
|
|
4
|
+
* 缓存键由 URL + 请求数据序列化生成,确保相同参数命中同一缓存。
|
|
5
|
+
* 过期条目在读取时惰性删除,无需定时清理。
|
|
6
|
+
* Provides TTL (Time-To-Live) based in-memory caching for query requests.
|
|
7
|
+
* Cache keys are generated from URL + serialized request data, ensuring identical
|
|
8
|
+
* parameters hit the same cache entry. Expired entries are lazily evicted on read,
|
|
9
|
+
* requiring no periodic cleanup.
|
|
10
|
+
*/
|
|
11
|
+
import { buildKey } from './common';
|
|
12
|
+
/** 内存缓存存储,键为 "url::data" 序列化字符串 / In-memory store, keyed by "url::data" serialized string */
|
|
13
|
+
const store = new Map();
|
|
14
|
+
/**
|
|
15
|
+
* 读取缓存 / Read from cache
|
|
16
|
+
* @param url - 请求地址 / Request URL
|
|
17
|
+
* @param data - 请求体数据 / Request body data
|
|
18
|
+
* @returns 缓存命中返回数据,未命中或已过期返回 null / Cached data on hit, null on miss or expiration
|
|
19
|
+
*/
|
|
20
|
+
export function cacheGet(url, data) {
|
|
21
|
+
const key = buildKey(url, data);
|
|
22
|
+
const entry = store.get(key);
|
|
23
|
+
if (!entry)
|
|
24
|
+
return null;
|
|
25
|
+
// 惰性删除:已过期的条目在读取时清除 / Lazy eviction: expired entries are removed on read
|
|
26
|
+
if (Date.now() > entry.expireAt) {
|
|
27
|
+
store.delete(key);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return entry.data;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 写入缓存 / Write to cache
|
|
34
|
+
* @param url - 请求地址 / Request URL
|
|
35
|
+
* @param data - 请求体数据 / Request body data
|
|
36
|
+
* @param value - 要缓存的数据 / Data to cache
|
|
37
|
+
* @param ttl - 缓存有效期(毫秒)/ Cache TTL in milliseconds
|
|
38
|
+
*/
|
|
39
|
+
export function cacheSet(url, data, value, ttl) {
|
|
40
|
+
const key = buildKey(url, data);
|
|
41
|
+
store.set(key, { data: value, expireAt: Date.now() + ttl });
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 删除指定缓存条目 / Delete a specific cache entry
|
|
45
|
+
* @param url - 请求地址 / Request URL
|
|
46
|
+
* @param data - 请求体数据 / Request body data
|
|
47
|
+
* @returns 是否成功删除 / Whether the entry was successfully deleted
|
|
48
|
+
*/
|
|
49
|
+
export function cacheDelete(url, data) {
|
|
50
|
+
return store.delete(buildKey(url, data));
|
|
51
|
+
}
|
|
52
|
+
/** 清空所有缓存 / Clear all cache entries */
|
|
53
|
+
export function cacheClear() {
|
|
54
|
+
store.clear();
|
|
55
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file 公共工具函数 / Common Utility Functions
|
|
3
|
+
* @description 提供 DataHub 内部各模块共享的工具函数,
|
|
4
|
+
* 避免在 cache、dedup、idempotent 等模块中重复实现。
|
|
5
|
+
* 当前提供 buildKey 函数,用于生成标准化的缓存/去重/幂等键。
|
|
6
|
+
* Provides shared utility functions for DataHub internal modules,
|
|
7
|
+
* avoiding duplicate implementations across cache, dedup, idempotent, etc.
|
|
8
|
+
* Currently provides buildKey for generating standardized cache/dedup/idempotent keys.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* 生成标准化的键 / Generate a standardized key
|
|
12
|
+
* @param url - 请求地址 / Request URL
|
|
13
|
+
* @param data - 请求体数据 / Request body data
|
|
14
|
+
* @returns 唯一键,格式为 "url::JSON(data)" / Unique key in format "url::JSON(data)"
|
|
15
|
+
* @description 用于缓存、去重、幂等防护等模块的键生成,
|
|
16
|
+
* 确保相同 URL + 相同数据命中同一键。
|
|
17
|
+
* Used for key generation in cache, dedup, idempotent guard modules,
|
|
18
|
+
* ensuring identical URL + data hit the same key.
|
|
19
|
+
*/
|
|
20
|
+
export function buildKey(url, data) {
|
|
21
|
+
const serialized = data === undefined ? 'null' : JSON.stringify(data);
|
|
22
|
+
return `${url}::${serialized}`;
|
|
23
|
+
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* ]);
|
|
23
23
|
* // r1 === r2,共享同一结果 / r1 === r2, sharing the same result
|
|
24
24
|
*/
|
|
25
|
-
export declare function dedupTrack<T>(url: string, data: unknown
|
|
25
|
+
export declare function dedupTrack<T>(url: string, data: unknown, factory: () => Promise<T>): Promise<T>;
|
|
26
26
|
/** 清空所有去重记录(一般用于测试或重置状态)/ Clear all dedup records (typically for testing or state reset) */
|
|
27
27
|
export declare function dedupClear(): void;
|
|
28
28
|
//# sourceMappingURL=dedup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../../../../src/core/datahub/utils/dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../../../../src/core/datahub/utils/dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,CAAC,CAAC,CAqBZ;AAED,4FAA4F;AAC5F,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file 请求去重工具 / Request Deduplication Utility
|
|
3
|
+
* @description 对查询类请求进行去重处理:当多个相同请求并发时,
|
|
4
|
+
* 只实际发出一次请求,所有调用方共享同一个 Promise 结果。
|
|
5
|
+
* 请求完成后自动清理,不影响后续正常请求。
|
|
6
|
+
* Deduplicates query requests: when multiple identical requests are concurrent,
|
|
7
|
+
* only one actual request is sent, and all callers share the same Promise result.
|
|
8
|
+
* Pending entries are automatically cleaned up after completion, not affecting subsequent requests.
|
|
9
|
+
*/
|
|
10
|
+
import { buildKey } from './common';
|
|
11
|
+
/** 正在进行的请求映射,键为 "url::data",值为进行中的 Promise / In-flight request map, keyed by "url::data", valued by pending Promise */
|
|
12
|
+
const pending = new Map();
|
|
13
|
+
/**
|
|
14
|
+
* 去重追踪:相同请求并发时复用已有 Promise / Dedup tracking: reuse existing Promise for concurrent identical requests
|
|
15
|
+
* @param url - 请求地址 / Request URL
|
|
16
|
+
* @param data - 请求体数据 / Request body data
|
|
17
|
+
* @param factory - 实际发起请求的工厂函数 / Factory function that performs the actual request
|
|
18
|
+
* @returns 请求结果 Promise(可能是新建的,也可能是复用的)/ Request result Promise (may be new or reused)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // 两个并发调用只会发出一次实际请求 / Two concurrent calls result in only one actual request
|
|
22
|
+
* const [r1, r2] = await Promise.all([
|
|
23
|
+
* dedupTrack('/order/query', { id: 1 }, () => fetch(...)),
|
|
24
|
+
* dedupTrack('/order/query', { id: 1 }, () => fetch(...)),
|
|
25
|
+
* ]);
|
|
26
|
+
* // r1 === r2,共享同一结果 / r1 === r2, sharing the same result
|
|
27
|
+
*/
|
|
28
|
+
export function dedupTrack(url, data, factory) {
|
|
29
|
+
const key = buildKey(url, data);
|
|
30
|
+
// 已有相同请求正在进行,直接复用 / Same request already in-flight, reuse directly
|
|
31
|
+
const existing = pending.get(key);
|
|
32
|
+
if (existing)
|
|
33
|
+
return existing;
|
|
34
|
+
// 首次请求,创建 Promise 并注册 / First request, create Promise and register
|
|
35
|
+
const promise = factory()
|
|
36
|
+
.then((result) => {
|
|
37
|
+
// 请求成功后清理注册表 / Clean up registry after success
|
|
38
|
+
pending.delete(key);
|
|
39
|
+
return result;
|
|
40
|
+
})
|
|
41
|
+
.catch((err) => {
|
|
42
|
+
// 请求失败也要清理,避免后续请求被永久阻塞 / Clean up on failure too, preventing permanent blocking
|
|
43
|
+
pending.delete(key);
|
|
44
|
+
throw err;
|
|
45
|
+
});
|
|
46
|
+
pending.set(key, promise);
|
|
47
|
+
return promise;
|
|
48
|
+
}
|
|
49
|
+
/** 清空所有去重记录(一般用于测试或重置状态)/ Clear all dedup records (typically for testing or state reset) */
|
|
50
|
+
export function dedupClear() {
|
|
51
|
+
pending.clear();
|
|
52
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file 幂等防护工具 / Idempotent Guard Utility
|
|
3
|
+
* @description 对提交类请求进行幂等防护:在请求未完成前,阻止相同参数的重复提交。
|
|
4
|
+
* 与去重(dedup)不同,幂等防护是"拒绝"而非"复用"——
|
|
5
|
+
* 提交类请求不能简单复用结果,必须明确阻止重复操作。
|
|
6
|
+
* Provides idempotent protection for submit requests: blocks duplicate submissions
|
|
7
|
+
* with the same parameters while a request is still in-flight.
|
|
8
|
+
* Unlike dedup, the idempotent guard "rejects" rather than "reuses" —
|
|
9
|
+
* submit requests cannot simply reuse results; duplicate operations must be explicitly blocked.
|
|
10
|
+
*/
|
|
11
|
+
import { buildKey } from './common';
|
|
12
|
+
import { DataHubError } from '../../datahub/types';
|
|
13
|
+
/** 幂等锁映射,键为 "url::data",值为进行中的 Promise / Idempotent lock map, keyed by "url::data", valued by in-flight Promise */
|
|
14
|
+
const idempotentLocks = new Map();
|
|
15
|
+
/**
|
|
16
|
+
* 幂等防护:阻止重复提交 / Idempotent guard: block duplicate submissions
|
|
17
|
+
* @param url - 请求地址 / Request URL
|
|
18
|
+
* @param data - 请求体数据 / Request body data
|
|
19
|
+
* @param factory - 实际发起请求的工厂函数 / Factory function that performs the actual request
|
|
20
|
+
* @returns 请求结果 Promise / Request result Promise
|
|
21
|
+
* @throws 重复提交时直接 reject,提示已被拦截 / Rejects on duplicate submission with a blocked message
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // 用户快速双击提交按钮 / User double-clicks the submit button
|
|
25
|
+
* try {
|
|
26
|
+
* await idempotentGuard('/order/pay', { orderId: '1' }, () => fetch(...));
|
|
27
|
+
* } catch (e) {
|
|
28
|
+
* // 第二次调用会被拦截,抛出 "duplicate submit blocked" 错误
|
|
29
|
+
* // The second call is blocked, throwing a "duplicate submit blocked" error
|
|
30
|
+
* }
|
|
31
|
+
*/
|
|
32
|
+
export function idempotentGuard(url, data, factory) {
|
|
33
|
+
const key = buildKey(url, data);
|
|
34
|
+
// 已有相同请求正在进行,直接拒绝(而非复用)/ Same request in-flight, reject directly (not reuse)
|
|
35
|
+
const existing = idempotentLocks.get(key);
|
|
36
|
+
if (existing) {
|
|
37
|
+
return Promise.reject(new DataHubError({
|
|
38
|
+
code: 'DuplicateSubmit',
|
|
39
|
+
message: `[DataHub] Idempotent guard: duplicate submit blocked for ${url}`,
|
|
40
|
+
url
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
// 首次提交,加锁并执行 / First submission, acquire lock and execute
|
|
44
|
+
const promise = factory()
|
|
45
|
+
.then((result) => {
|
|
46
|
+
// 请求完成后释放锁 / Release lock after completion
|
|
47
|
+
idempotentLocks.delete(key);
|
|
48
|
+
return result;
|
|
49
|
+
})
|
|
50
|
+
.catch((err) => {
|
|
51
|
+
// 请求失败也要释放锁,允许用户重试 / Release lock on failure too, allowing user retry
|
|
52
|
+
idempotentLocks.delete(key);
|
|
53
|
+
throw err;
|
|
54
|
+
});
|
|
55
|
+
idempotentLocks.set(key, promise);
|
|
56
|
+
return promise;
|
|
57
|
+
}
|
|
58
|
+
/** 清空所有幂等锁(一般用于测试或重置状态)/ Clear all idempotent locks (typically for testing or state reset) */
|
|
59
|
+
export function idempotentClear() {
|
|
60
|
+
idempotentLocks.clear();
|
|
61
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file URL 查询动作识别 / URL Query Action Detection
|
|
3
|
+
* @description 根据 URL 最后一段路径判断请求是否为查询类动作。
|
|
4
|
+
* 识别关键词可配置,默认:query、list、get。
|
|
5
|
+
* 用于策略自动选择:查询类走缓存+去重,提交类走幂等防护。
|
|
6
|
+
* Determines whether a request is a query action based on the last URL path segment.
|
|
7
|
+
* Recognized keywords are configurable, defaulting to: query, list, get.
|
|
8
|
+
* Used for automatic strategy selection: query → cache + dedup, submit → idempotent guard.
|
|
9
|
+
*/
|
|
10
|
+
/** 默认查询类动作关键词列表 / Default query action keyword list */
|
|
11
|
+
const DEFAULT_QUERY_KEYWORDS = ['query', 'list', 'get'];
|
|
12
|
+
/** 当前生效的查询关键词列表 / Currently active query keyword list */
|
|
13
|
+
let queryKeywords = [...DEFAULT_QUERY_KEYWORDS];
|
|
14
|
+
/**
|
|
15
|
+
* 设置查询类动作关键词 / Set query action keywords
|
|
16
|
+
* @param keywords - 自定义关键词列表,将替换默认列表 / Custom keyword list, replaces the default list
|
|
17
|
+
* @description 允许外部扩展或覆盖默认的查询关键词,
|
|
18
|
+
* 例如添加 "search"、"fetch" 等自定义查询动作。
|
|
19
|
+
* Allows external extension or override of default query keywords,
|
|
20
|
+
* e.g. adding "search", "fetch" as custom query actions.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* setQueryKeywords(['query', 'list', 'get', 'search', 'fetch']);
|
|
24
|
+
*/
|
|
25
|
+
export function setQueryKeywords(keywords) {
|
|
26
|
+
queryKeywords = keywords;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 获取当前查询关键词列表 / Get current query keyword list
|
|
30
|
+
* @returns 当前生效的关键词列表副本 / Copy of currently active keyword list
|
|
31
|
+
*/
|
|
32
|
+
export function getQueryKeywords() {
|
|
33
|
+
return [...queryKeywords];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 判断 URL 是否为查询类动作 / Determine if the URL represents a query action
|
|
37
|
+
* @param url - 请求地址,如 "/order/query"、"/user/list" / Request URL, e.g. "/order/query", "/user/list"
|
|
38
|
+
* @returns true 表示查询类动作,false 表示提交类动作 / true for query action, false for submit action
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* isQueryAction('/order/query') // true
|
|
42
|
+
* isQueryAction('/order/submit') // false
|
|
43
|
+
* isQueryAction('/user/list') // true
|
|
44
|
+
* isQueryAction('/order/pay') // false
|
|
45
|
+
*/
|
|
46
|
+
export function isQueryAction(url) {
|
|
47
|
+
let cleaned = url;
|
|
48
|
+
while (cleaned.endsWith('/')) {
|
|
49
|
+
cleaned = cleaned.slice(0, -1);
|
|
50
|
+
}
|
|
51
|
+
const segment = cleaned.split('/').pop()?.toLowerCase() ?? '';
|
|
52
|
+
return queryKeywords.some((kw) => segment === kw || segment.startsWith(kw + '/'));
|
|
53
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file 全局 Loading 状态管理 / Global Loading State Management
|
|
3
|
+
* @description 提供请求级别的 loading 状态追踪与订阅机制。
|
|
4
|
+
* 业务层可监听 loading 变化来控制 UI 中的加载指示器。
|
|
5
|
+
* 基于 URL 粒度管理,使用计数模式支持同一 URL 的多次并发请求叠加,
|
|
6
|
+
* 只有计数归零时才触发 loading=false 回调。
|
|
7
|
+
* Provides request-level loading state tracking and subscription mechanism.
|
|
8
|
+
* The business layer can listen for loading changes to control UI loading indicators.
|
|
9
|
+
* Managed at URL granularity, using a counter model to support overlapping requests
|
|
10
|
+
* for the same URL. Only triggers loading=false callback when the count reaches zero.
|
|
11
|
+
*/
|
|
12
|
+
/** 已注册的监听器集合 / Registered listener set */
|
|
13
|
+
const listeners = new Set();
|
|
14
|
+
/** 每个 URL 的并发请求计数 / Concurrent request count per URL */
|
|
15
|
+
const counterMap = new Map();
|
|
16
|
+
/**
|
|
17
|
+
* 标记请求开始 / Mark request as started
|
|
18
|
+
* @param url - 请求地址 / Request URL
|
|
19
|
+
* @description 计数 +1,首次从 0→1 时通知监听器 loading=true
|
|
20
|
+
* Counter +1, notifies listeners loading=true on first transition 0→1
|
|
21
|
+
*/
|
|
22
|
+
export function loadingStart(url) {
|
|
23
|
+
const prev = counterMap.get(url) ?? 0;
|
|
24
|
+
counterMap.set(url, prev + 1);
|
|
25
|
+
if (prev === 0) {
|
|
26
|
+
for (const fn of listeners) {
|
|
27
|
+
fn(url, true);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 标记请求结束 / Mark request as ended
|
|
33
|
+
* @param url - 请求地址 / Request URL
|
|
34
|
+
* @description 计数 -1,归零时通知监听器 loading=false
|
|
35
|
+
* Counter -1, notifies listeners loading=false when count reaches zero
|
|
36
|
+
*/
|
|
37
|
+
export function loadingEnd(url) {
|
|
38
|
+
const prev = counterMap.get(url) ?? 0;
|
|
39
|
+
if (prev <= 1) {
|
|
40
|
+
counterMap.delete(url);
|
|
41
|
+
if (prev === 1) {
|
|
42
|
+
for (const fn of listeners) {
|
|
43
|
+
fn(url, false);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
counterMap.set(url, prev - 1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 查询指定 URL 是否正在加载 / Check if the specified URL is currently loading
|
|
53
|
+
* @param url - 请求地址 / Request URL
|
|
54
|
+
* @returns 是否正在加载 / Whether it is currently loading
|
|
55
|
+
*/
|
|
56
|
+
export function isLoading(url) {
|
|
57
|
+
return (counterMap.get(url) ?? 0) > 0;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 订阅 loading 状态变更 / Subscribe to loading state changes
|
|
61
|
+
* @param fn - 状态变更回调 / State change callback
|
|
62
|
+
* @returns 取消订阅函数 / Unsubscribe function
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* const unsubscribe = onLoadingChange((url, loading) => {
|
|
66
|
+
* if (url === '/order/query') {
|
|
67
|
+
* setSpinnerVisible(loading);
|
|
68
|
+
* }
|
|
69
|
+
* });
|
|
70
|
+
* // 组件卸载时取消订阅 / Unsubscribe on component unmount
|
|
71
|
+
* unsubscribe();
|
|
72
|
+
*/
|
|
73
|
+
export function onLoadingChange(fn) {
|
|
74
|
+
listeners.add(fn);
|
|
75
|
+
return () => {
|
|
76
|
+
listeners.delete(fn);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../src/core/filter/__tests__/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach, beforeAll } from 'vitest';
|
|
2
|
+
import { AmountFilter, DateFilter, EmptyFilter, BytesFilter, TimeAgoFilter } from '../../filter/builtins';
|
|
3
|
+
import { FilterFactory } from '../../filter/factory';
|
|
4
|
+
import { filterFactory } from '../../filter/index';
|
|
5
|
+
import { registerAitheLocale } from '../../../styles/i18n';
|
|
6
|
+
import { en as enLocale } from '../../../styles/i18n/locales/en-US';
|
|
7
|
+
beforeAll(() => {
|
|
8
|
+
registerAitheLocale('en-US', enLocale);
|
|
9
|
+
});
|
|
10
|
+
// --- AmountFilter ---
|
|
11
|
+
describe('AmountFilter', () => {
|
|
12
|
+
const filter = new AmountFilter();
|
|
13
|
+
it('formats number to 2 decimal places', () => {
|
|
14
|
+
expect(filter.apply(123.4)).toBe('123.40');
|
|
15
|
+
expect(filter.apply(0)).toBe('0.00');
|
|
16
|
+
expect(filter.apply(100)).toBe('100.00');
|
|
17
|
+
});
|
|
18
|
+
it('parses numeric string', () => {
|
|
19
|
+
expect(filter.apply('123.456')).toBe('123.46');
|
|
20
|
+
expect(filter.apply('0')).toBe('0.00');
|
|
21
|
+
});
|
|
22
|
+
it('returns -- for null/undefined', () => {
|
|
23
|
+
expect(filter.apply(null)).toBe('--');
|
|
24
|
+
expect(filter.apply(undefined)).toBe('--');
|
|
25
|
+
});
|
|
26
|
+
it('returns -- for non-numeric string', () => {
|
|
27
|
+
expect(filter.apply('abc')).toBe('--');
|
|
28
|
+
expect(filter.apply('')).toBe('--');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
// --- DateFilter ---
|
|
32
|
+
describe('DateFilter', () => {
|
|
33
|
+
const filter = new DateFilter();
|
|
34
|
+
it('formats Date object with default format', () => {
|
|
35
|
+
const d = new Date(2024, 0, 15, 14, 30, 45);
|
|
36
|
+
expect(filter.apply(d)).toBe('2024-01-15 14:30:45');
|
|
37
|
+
});
|
|
38
|
+
it('formats with custom format', () => {
|
|
39
|
+
const d = new Date(2024, 0, 15);
|
|
40
|
+
expect(filter.apply(d, 'yyyy/MM/dd')).toBe('2024/01/15');
|
|
41
|
+
expect(filter.apply(d, 'MM-dd')).toBe('01-15');
|
|
42
|
+
});
|
|
43
|
+
it('parses timestamp (ms)', () => {
|
|
44
|
+
const ts = new Date(2024, 5, 1).getTime();
|
|
45
|
+
expect(filter.apply(ts, 'yyyy-MM-dd')).toBe('2024-06-01');
|
|
46
|
+
});
|
|
47
|
+
it('parses date string', () => {
|
|
48
|
+
expect(filter.apply('2024-01-15', 'yyyy/MM/dd')).toBe('2024/01/15');
|
|
49
|
+
});
|
|
50
|
+
it('returns -- for null/undefined/empty', () => {
|
|
51
|
+
expect(filter.apply(null)).toBe('--');
|
|
52
|
+
expect(filter.apply(undefined)).toBe('--');
|
|
53
|
+
expect(filter.apply('')).toBe('--');
|
|
54
|
+
});
|
|
55
|
+
it('returns -- for invalid date string', () => {
|
|
56
|
+
expect(filter.apply('not-a-date')).toBe('--');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
// --- EmptyFilter ---
|
|
60
|
+
describe('EmptyFilter', () => {
|
|
61
|
+
const filter = new EmptyFilter();
|
|
62
|
+
it('returns value as string for non-empty', () => {
|
|
63
|
+
expect(filter.apply('hello')).toBe('hello');
|
|
64
|
+
expect(filter.apply(0)).toBe('0');
|
|
65
|
+
expect(filter.apply(false)).toBe('false');
|
|
66
|
+
});
|
|
67
|
+
it('returns placeholder for null/undefined', () => {
|
|
68
|
+
expect(filter.apply(null)).toBe('--');
|
|
69
|
+
expect(filter.apply(undefined)).toBe('--');
|
|
70
|
+
});
|
|
71
|
+
it('returns placeholder for empty string', () => {
|
|
72
|
+
expect(filter.apply('')).toBe('--');
|
|
73
|
+
});
|
|
74
|
+
it('returns placeholder for NaN', () => {
|
|
75
|
+
expect(filter.apply(NaN)).toBe('--');
|
|
76
|
+
});
|
|
77
|
+
it('supports custom placeholder', () => {
|
|
78
|
+
expect(filter.apply(null, '-')).toBe('-');
|
|
79
|
+
expect(filter.apply('', 'N/A')).toBe('N/A');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
// --- BytesFilter ---
|
|
83
|
+
describe('BytesFilter', () => {
|
|
84
|
+
const filter = new BytesFilter();
|
|
85
|
+
it('formats bytes in IEC (1024) by default', () => {
|
|
86
|
+
expect(filter.apply(0)).toBe('0 B');
|
|
87
|
+
expect(filter.apply(500)).toBe('500 B');
|
|
88
|
+
expect(filter.apply(1024)).toBe('1.00 KiB');
|
|
89
|
+
expect(filter.apply(1536)).toBe('1.50 KiB');
|
|
90
|
+
expect(filter.apply(1048576)).toBe('1.00 MiB');
|
|
91
|
+
expect(filter.apply(1073741824)).toBe('1.00 GiB');
|
|
92
|
+
});
|
|
93
|
+
it('formats bytes in SI (1000)', () => {
|
|
94
|
+
expect(filter.apply(1000, '1000')).toBe('1.00 KB');
|
|
95
|
+
expect(filter.apply(1000000, '1000')).toBe('1.00 MB');
|
|
96
|
+
expect(filter.apply(1000000000, '1000')).toBe('1.00 GB');
|
|
97
|
+
});
|
|
98
|
+
it('returns -- for null/undefined', () => {
|
|
99
|
+
expect(filter.apply(null)).toBe('--');
|
|
100
|
+
expect(filter.apply(undefined)).toBe('--');
|
|
101
|
+
});
|
|
102
|
+
it('returns -- for negative values', () => {
|
|
103
|
+
expect(filter.apply(-1)).toBe('--');
|
|
104
|
+
});
|
|
105
|
+
it('returns -- for non-numeric string', () => {
|
|
106
|
+
expect(filter.apply('abc')).toBe('--');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
// --- TimeAgoFilter ---
|
|
110
|
+
describe('TimeAgoFilter', () => {
|
|
111
|
+
const filter = new TimeAgoFilter();
|
|
112
|
+
const now = Date.now();
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
vi.useFakeTimers();
|
|
115
|
+
vi.setSystemTime(now);
|
|
116
|
+
});
|
|
117
|
+
afterEach(() => {
|
|
118
|
+
vi.useRealTimers();
|
|
119
|
+
});
|
|
120
|
+
it('returns just now for < 60s', () => {
|
|
121
|
+
expect(filter.apply(now)).toBe('just now');
|
|
122
|
+
expect(filter.apply(now - 30_000)).toBe('just now');
|
|
123
|
+
});
|
|
124
|
+
it('returns minutes ago', () => {
|
|
125
|
+
expect(filter.apply(now - 120_000)).toBe('2 minutes ago');
|
|
126
|
+
expect(filter.apply(now - 3_600_000 + 1)).toBe('59 minutes ago');
|
|
127
|
+
});
|
|
128
|
+
it('returns hours ago', () => {
|
|
129
|
+
expect(filter.apply(now - 7_200_000)).toBe('2 hours ago');
|
|
130
|
+
expect(filter.apply(now - 86_400_000 + 1)).toBe('23 hours ago');
|
|
131
|
+
});
|
|
132
|
+
it('returns days ago', () => {
|
|
133
|
+
expect(filter.apply(now - 172_800_000)).toBe('2 days ago');
|
|
134
|
+
expect(filter.apply(now - 2_592_000_000 + 1)).toBe('29 days ago');
|
|
135
|
+
});
|
|
136
|
+
it('returns months ago', () => {
|
|
137
|
+
expect(filter.apply(now - 5_184_000_000)).toBe('2 months ago');
|
|
138
|
+
expect(filter.apply(now - 25_920_000_000)).toBe('10 months ago');
|
|
139
|
+
});
|
|
140
|
+
it('returns date for > 1 year', () => {
|
|
141
|
+
const past = new Date(now - 31_104_000_000 - 86_400_000);
|
|
142
|
+
const y = past.getFullYear();
|
|
143
|
+
const m = String(past.getMonth() + 1).padStart(2, '0');
|
|
144
|
+
const d = String(past.getDate()).padStart(2, '0');
|
|
145
|
+
expect(filter.apply(past.getTime())).toBe(`${y}-${m}-${d}`);
|
|
146
|
+
});
|
|
147
|
+
it('handles future times', () => {
|
|
148
|
+
expect(filter.apply(now + 120_000)).toBe('in 2 minutes');
|
|
149
|
+
expect(filter.apply(now + 7_200_000)).toBe('in 2 hours');
|
|
150
|
+
expect(filter.apply(now + 172_800_000)).toBe('in 2 days');
|
|
151
|
+
expect(filter.apply(now + 5_184_000_000)).toBe('in 2 months');
|
|
152
|
+
});
|
|
153
|
+
it('returns -- for null/undefined/empty', () => {
|
|
154
|
+
expect(filter.apply(null)).toBe('--');
|
|
155
|
+
expect(filter.apply(undefined)).toBe('--');
|
|
156
|
+
expect(filter.apply('')).toBe('--');
|
|
157
|
+
});
|
|
158
|
+
it('returns -- for invalid date string', () => {
|
|
159
|
+
expect(filter.apply('not-a-date')).toBe('--');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
// --- FilterFactory ---
|
|
163
|
+
describe('FilterFactory', () => {
|
|
164
|
+
it('registers built-in filters', () => {
|
|
165
|
+
const factory = new FilterFactory();
|
|
166
|
+
expect(factory.has('amount')).toBe(true);
|
|
167
|
+
expect(factory.has('date')).toBe(true);
|
|
168
|
+
expect(factory.has('empty')).toBe(true);
|
|
169
|
+
expect(factory.has('bytes')).toBe(true);
|
|
170
|
+
expect(factory.has('timeAgo')).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
it('registers custom filter', () => {
|
|
173
|
+
const factory = new FilterFactory();
|
|
174
|
+
class UpperFilter {
|
|
175
|
+
apply(value) {
|
|
176
|
+
return value.toUpperCase();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
factory.register('upper', UpperFilter);
|
|
180
|
+
expect(factory.has('upper')).toBe(true);
|
|
181
|
+
expect(factory.get('upper')?.apply('hello')).toBe('HELLO');
|
|
182
|
+
});
|
|
183
|
+
it('formats value with expression string', () => {
|
|
184
|
+
const factory = new FilterFactory();
|
|
185
|
+
expect(factory.format(123.4, 'amount')).toBe('123.40');
|
|
186
|
+
expect(factory.format(null, 'empty')).toBe('--');
|
|
187
|
+
});
|
|
188
|
+
it('formats value with chained expression', () => {
|
|
189
|
+
const factory = new FilterFactory();
|
|
190
|
+
expect(factory.format(null, 'empty | empty -')).toBe('--');
|
|
191
|
+
});
|
|
192
|
+
it('returns original value for unknown filter', () => {
|
|
193
|
+
const factory = new FilterFactory();
|
|
194
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
195
|
+
expect(factory.format('test', 'unknown')).toBe('test');
|
|
196
|
+
expect(warn).toHaveBeenCalled();
|
|
197
|
+
warn.mockRestore();
|
|
198
|
+
});
|
|
199
|
+
it('parses expression string', () => {
|
|
200
|
+
const factory = new FilterFactory();
|
|
201
|
+
expect(factory.parse('amount')).toEqual([{ name: 'amount', args: [] }]);
|
|
202
|
+
expect(factory.parse('date yyyy/MM/dd')).toEqual([{ name: 'date', args: ['yyyy/MM/dd'] }]);
|
|
203
|
+
expect(factory.parse('amount | empty')).toEqual([
|
|
204
|
+
{ name: 'amount', args: [] },
|
|
205
|
+
{ name: 'empty', args: [] },
|
|
206
|
+
]);
|
|
207
|
+
});
|
|
208
|
+
it('stringifies expressions', () => {
|
|
209
|
+
const factory = new FilterFactory();
|
|
210
|
+
expect(factory.stringify([{ name: 'amount', args: [] }])).toBe('amount');
|
|
211
|
+
expect(factory.stringify([{ name: 'date', args: ['yyyy/MM/dd'] }])).toBe('date yyyy/MM/dd');
|
|
212
|
+
expect(factory.stringify([
|
|
213
|
+
{ name: 'amount', args: [] },
|
|
214
|
+
{ name: 'empty', args: [] },
|
|
215
|
+
])).toBe('amount | empty');
|
|
216
|
+
});
|
|
217
|
+
it('names() returns registered filter names', () => {
|
|
218
|
+
const factory = new FilterFactory();
|
|
219
|
+
const names = factory.names();
|
|
220
|
+
expect(names).toContain('amount');
|
|
221
|
+
expect(names).toContain('date');
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
// --- filterFactory instance ---
|
|
225
|
+
describe('filterFactory instance', () => {
|
|
226
|
+
it('is a FilterFactory instance with built-in filters', () => {
|
|
227
|
+
expect(filterFactory).toBeInstanceOf(FilterFactory);
|
|
228
|
+
expect(filterFactory.has('amount')).toBe(true);
|
|
229
|
+
});
|
|
230
|
+
});
|