@composy/shared-core

v0.0.2

Published

Framework-agnostic shared utilities, protocols, icons, and types for LDesign

Downloads

271

Readme

@composy/shared-core

框架无关的 LDesign 共享核心包。该包是 packages/shared 的主要功能实现层, Vue/React/Lit/Vanilla 等适配包都应优先复用这里的工具、协议和类型。

能力范围

| 模块 | 说明 | 入口路径 | | ---------------- | ------------------------------------------------------------------------------ | ------------------------------------- | | utils | 数组、字符串、树、校验、格式化、缓存、事件总线、HTTP、DOM、性能与 storage 工具 | @composy/shared-core/utils | | protocols | 选择器等跨框架协议类型与预设 | @composy/shared-core/protocols | | types | 业务通用类型、深度工具类型、设备和表单类型 | @composy/shared-core/types | | icons | LDesign 图标名到 Lucide 图标名的映射 | @composy/shared-core/icons | | web-components | 框架无关 Web Component(ldesign-view-state) | @composy/shared-core/web-components | | error-handler | 统一错误处理(PluginError、ErrorHandler) | @composy/shared-core/error-handler |

工具函数一览

数组工具 (utils/array)

  • unique / uniqueBy — 去重
  • chunk / groupBy — 分割与分组
  • flatten / flattenDeep — 扁平化
  • intersection / union / difference — 集合运算
  • shuffle / sample — 随机操作
  • compact — 移除假值
  • sum / average / max / min — 数学运算

字符串工具 (utils/string)

  • capitalize / camelCase / kebabCase / snakeCase — 大小写转换
  • template / templateReplacer — 模板字符串
  • truncate / padStart / padEnd — 截断与填充
  • escapeHtml / unescapeHtml — HTML 转义

DOM 工具 (utils/dom)

  • on / off / once / clickOut — 事件绑定
  • hasClass / addClass / removeClass — 类名操作
  • getScrollContainer / scrollTo / scrollSelectedIntoView — 滚动控制
  • elementInViewport / isTextEllipsis / isFixed — 元素检测

校验工具 (utils/validate)

  • isValidEmail / isValidPhone / isValidUrl / isValidIPv4 / isValidIPv6 — 格式校验
  • validatePassword / isStrongPassword — 密码强度
  • isNumeric / isInteger / isFloat / isPositive — 数值校验
  • isEmpty / isEqual / deepClone — 值操作

缓存工具 (utils/cache)

  • createLRUCache — LRU 缓存
  • memoize — 函数记忆化
  • cached — 装饰器缓存

缓存 TTL 省略时使用 defaultTTL(默认 5 分钟);传入 ttl: 0 表示立即过期, 传入 Infinity 表示不自动过期。undefined 也会作为有效缓存值命中,调用方不需要 用特殊哨兵值区分“已缓存”和“未缓存”。

MemoryCache.stats() 会累计 get/has 命中、未命中、写入、删除和 LRU 驱逐次数,并返回 hitRate 与估算内存占用;resetStats() 只清零统计,不会清空条目。memoize() 与 cached() 对同一 key 的并发 Promise 使用进程内 single-flight,异步 factory 失败后会释放协调状态,下一次 调用可以正常重试。

LRU 缓存会在成功的 get()、has() 和每次 set() 后刷新条目顺序;容量满时按最久未访问顺序 驱逐。顺序维护和驱逐使用 Map 插入顺序,避免每次新增时扫描整份缓存;空字符串也是有效 key。

事件总线 (utils/eventBus)

  • EventBus — 类型安全的事件总线

once() 监听器会在回调执行前移除,因此回调重入派发或抛出异常时也只执行一次;emitAsync() 同样在 等待监听器 Promise 前完成移除。

资源生命周期 (utils/disposable)

createDisposableScope() 可将计时器、监听器、observer 等同步清理函数绑定到同一生命周期;scope 按注册顺序的逆序释放资源,单项 disposer 可提前幂等执行,清理失败时会继续释放其他资源并最终抛出 DisposalError(其 errors 字段保留原始异常)。scope 已释放后新注册的资源会立即清理。

import { createDisposableScope } from '@composy/shared-core/utils/disposable'

const scope = createDisposableScope()
const timer = setInterval(refresh, 1_000)
scope.add(() => clearInterval(timer))

// 页面或服务结束时统一释放
scope.dispose()

Storage 工具 (utils/storage)

  • readStorageValue / writeStorageValue / removeStorageValue — SSR 安全存储读写
  • resolveBrowserStorage — 浏览器存储解析
  • parseStorageEventValue — storage 事件解析

Storage 工具示例

import {
  createJsonStorageSerializer,
  readStorageValue,
  writeStorageValue,
} from '@composy/shared-core/utils'

const serializer = createJsonStorageSerializer<{ theme: string }>()

writeStorageValue(
  {
    defaultValue: { theme: 'light' },
    key: 'settings',
    serializer,
    storage: localStorage,
  },
  { theme: 'dark' },
)

const settings = readStorageValue({
  defaultValue: { theme: 'light' },
  key: 'settings',
  serializer,
  storage: localStorage,
})

HTTP 请求取消

RequestOptions.signal 可接收外部 AbortSignal。客户端会把它与自身的超时控制合并, 请求完成或失败后都会释放超时定时器与取消监听器。

import { createHttpClient } from '@composy/shared-core/utils'

const client = createHttpClient({ baseURL: '/api' })
const controller = new AbortController()

const request = client.request({
  method: 'GET',
  signal: controller.signal,
  url: '/users',
})

// 页面离开或用户取消操作时调用。
controller.abort()
await request

错误处理示例

import { createPluginErrorHandler } from '@composy/shared-core/error-handler'

const err = createPluginErrorHandler('cache-plugin')

// 包装函数,自动捕获错误
const safeGet = err.wrap(() => cache.get(key))

// 直接抛出带插件名的错误
err.throw('缓存已满', 'CACHE_FULL')

handle() 可以接收任意抛出值并归一为 Error;同步函数、Promise 和 thenable 的失败都会 被包装为 PluginError。已注册处理器自身失败时只记录错误,不会让调用链再次中断。

类型说明

types/common.ts 提供完整的公共类型体系:

  • 框架节点:FrameworkNode、TNode、TNodeReturnValue
  • CSS/DOM:CSSSelector、AttachNode、ScrollContainer
  • 深度工具:DeepPartial、DeepRequired、DeepReadonly、Prettify
  • 通用工具:Nullable、Optional、Maybe、ValueOrFunction、ArrayOrSingle
  • 业务类型:ApiResponse、PaginationResponse、UploadFile、FormField、MenuItem
  • 主题/设备:ThemeConfig、DeviceInfo

开发约定

  • core 不依赖 Vue 或其他 UI 框架
  • 浏览器能力必须先做 SSR/权限异常保护
  • 公共函数需要显式返回类型和中文注释
  • 新增 core 行为需要补充 src/**/__tests__/*.test.ts 回归测试
  • 禁止在公共类型/参数/返回值中使用 any,统一使用 unknown 替代
  • 仅 Chrome-only 非标准 API(如 performance.memory)允许 eslint-disable + any,需注释说明原因

验证

pnpm --filter @composy/shared-core typecheck
pnpm --filter @composy/shared-core test:run
pnpm --filter @composy/shared-core build

构建产物覆盖 dist/es/esm/lib。

ESM 声明中的相对模块路径会补齐 .js,可由 TypeScript NodeNext 消费端直接解析。