yann-core 0.0.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,39 +1,77 @@
1
- # core-test-vue
1
+ # yann-core
2
2
 
3
- This template should help get you started developing with Vue 3 in Vite.
3
+ 用于 Vue 3.5 的定时器与状态工具。Vue 是 peer dependency,使用项目自身的 Vue 实例。
4
4
 
5
- ## Recommended IDE Setup
5
+ ## 定时器
6
6
 
7
- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
7
+ ```ts
8
+ import { useRafTimer } from 'yann-core'
8
9
 
9
- ## Type Support for `.vue` Imports in TS
10
+ const timer = useRafTimer(async () => {
11
+ await refreshData()
12
+ }, 1000, {
13
+ type: 'ignoreCallbackTime',
14
+ loop: true,
15
+ onError: (error) => console.error(error),
16
+ })
10
17
 
11
- TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
18
+ timer.pause()
19
+ timer.start() // 恢复暂停
20
+ timer.stop() // 永久停止;start 不会重新启动
21
+ ```
12
22
 
13
- ## Customize configuration
23
+ - 创建后自动开始,首次执行在间隔到期后的动画帧;默认间隔为 `1000 / 60` 毫秒。
24
+ - `ignoreCallbackTime`:从本次回调开始计算间隔;`waitAfterCallback`:从回调及错误报告完成后计算间隔。
25
+ - 每个实例最多执行一个回调,支持 Promise 和 thenable。长回调完成后若已过期,只在下一帧执行一次,不补发遗漏次数。
26
+ - 暂停冻结计时;恢复时仍等待尚未完成的回调。`stop` 和 Vue 作用域销毁会清理待调度任务并释放回调引用;用户创建的 Promise 不会自动取消。
27
+ - 异常报告后继续,未配置 `onError` 时使用 `console.error`。异步 `onError` 也会等待;报告器失败会捕获并记录。每次回调尝试,包括失败,都计入次数。
28
+ - `loop: true` 或 `Infinity` 无限循环,`false` 执行一次;有限数字向上取整且至少一次。`NaN` 和负无穷非法。
29
+ - 间隔必须是有限非负数;零间隔每帧最多执行一次。超长延时分段等待。无 RAF 环境(如 SSR)返回无操作的控制方法,不执行回调。
30
+ - 长间隔由 timeout 等待,距离截止时间 20ms 内由 RAF 检查。实际执行精度受帧率和浏览器后台限流影响。
14
31
 
15
- See [Vite Configuration Reference](https://vite.dev/config/).
32
+ ## 状态
16
33
 
17
- ## Project Setup
34
+ ```ts
35
+ import { useState } from 'yann-core'
18
36
 
19
- ```sh
20
- pnpm install
37
+ const [state, setState] = useState(0)
38
+ setState(1)
39
+
40
+ const [rows, setRows] = useState([{ id: 1 }], { shallow: true })
41
+ setRows([{ id: 2 }]) // 替换 .value 触发更新
21
42
  ```
22
43
 
23
- ### Compile and Hot-Reload for Development
44
+ 默认使用深层响应式 `ref`,对象属性中的嵌套 Ref 会解包;数组和 Map 中的 Ref 遵循 Vue 自身的规则。`shallow: true` 使用 `shallowRef`,保留输入对象与嵌套 Ref,不为普通对象增加深层代理。已有响应式对象不会被转换回普通对象。浅层内部修改需替换对象或使用 Vue 的 `triggerRef`。
24
45
 
25
- ```sh
26
- pnpm dev
46
+ 普通值、Ref 和 getter 只在初始化时求值一次,不持续同步源。若 getter 返回 Ref,则遵循 Vue 工厂的 Ref 复用行为;setter 收到根 Ref 时取其内部值再写入,保持读取类型与运行结果一致。比较与 `beforeSet` 仍接收原始输入。
47
+
48
+ ```ts
49
+ const [value, setValue] = useState(2, {
50
+ diff: true,
51
+ beforeSet: (incoming) => incoming * 2,
52
+ })
53
+ setValue(2) // false:比较相等,beforeSet 不执行
54
+ setValue(1) // true:先比较原始输入,再转换为 2
27
55
  ```
28
56
 
29
- ### Type-Check, Compile and Minify for Production
57
+ `diff: true` 默认深比较(支持数组、Map、循环引用),先做引用相等快速判断。提供 `compare(oldValue, newValue)` 时始终调用自定义比较器,并启用比较流程,即使未设置 `diff`。旧值类型与状态读取类型一致,新值和 `beforeSet` 使用原始输入类型。
58
+
59
+ setter 返回 `false` 表示比较判定相等而跳过设置,返回 `true` 表示接受设置;未启用比较时,即使 Vue 本身不触发更新,也返回 `true`。类型从根入口导出:`UseStateConfig<T, Shallow>`、`UseStateRef<T, Shallow>`、`UseStateReturn<T, Shallow>`、`Callback`、`ControlFunctions`、`RafTimerOptions`。状态类型第二个参数默认 `false`,动态布尔选项使用 `boolean`。
60
+
61
+ 类型纠错可能使依赖旧声明的代码报错:深层模式的对象 Ref 属性应读取 `state.value.nested`,而不是 `state.value.nested.value`;比较器旧值同样遵循解包类型。
62
+
63
+ ## 验证
30
64
 
31
65
  ```sh
66
+ pnpm install --frozen-lockfile
67
+ pnpm type-check
68
+ pnpm lint:check
69
+ pnpm test
32
70
  pnpm build
71
+ pnpm verify:package
72
+ pnpm benchmark
33
73
  ```
34
74
 
35
- ### Lint with [ESLint](https://eslint.org/)
75
+ `type-check` 同时编译运行测试和类型回归用例;`lint:check` 不修改文件。`verify:package` 检查打包后的 ESM、NodeNext/Bundler 类型消费和仅导入定时器时的 tree shaking。基准需要支持 `require(ESM)` 的 Node 22.12+ 及 Git 基线历史;可用 `YANN_BASELINE_REVISION` 指定比较提交。结果写入忽略的 `artifacts/`,方法和实测结果见 [PERFORMANCE.md](./PERFORMANCE.md)。
36
76
 
37
- ```sh
38
- pnpm lint
39
- ```
77
+ 构建内存与体积可用 `node scripts/measure-build.mjs optimized` 记录;该命令清理 TypeScript 增量缓存以测量冷类型检查。不自动发布版本。
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ import { useState as o } from "./useState.js";
2
+ import { useRafTimer as f } from "./useTimer.js";
3
+ export {
4
+ f as useRafTimer,
5
+ o as useState
6
+ };
@@ -0,0 +1,9 @@
1
+ /** @file 库统一出口,聚合导出全部 Hook 及其类型定义 */
2
+ /** 带差异比较能力的状态 Hook */
3
+ export { useState } from './useState/index.js';
4
+ /** 状态 Hook 关联类型:配置项、状态引用与返回元组 */
5
+ export type { UseStateConfig, UseStateRef, UseStateReturn } from './useState/index.js';
6
+ /** 基于 requestAnimationFrame 的定时器 Hook */
7
+ export { useRafTimer } from './useTimer/index.js';
8
+ /** 定时器 Hook 关联类型:回调、控制函数与配置项 */
9
+ export type { Callback, ControlFunctions, RafTimerOptions } from './useTimer/index.js';
@@ -0,0 +1,37 @@
1
+ import { MaybeRefOrGetter, Ref, ShallowRef, UnwrapRef } from 'vue';
2
+ /** 检测类型 T 是否为 any;是 any 时取 Yes 分支,否则取 No */
3
+ type IfAny<T, Yes, No> = 0 extends (1 & T) ? Yes : No;
4
+ /** 深层的状态引用类型:普通 Ref 原样返回,其余展开为 UnwrapRef 包装 */
5
+ type DeepStateRef<T> = [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T>;
6
+ /** 浅层的状态引用类型:仅做一层包装,避免深层解包 */
7
+ type ShallowStateRef<T> = Ref extends T ? T extends Ref ? IfAny<T, ShallowRef<T>, T> : ShallowRef<T> : ShallowRef<T>;
8
+ /** useState 返回的状态引用类型,按 shallow 开关在深浅两种引用间切换 */
9
+ export type UseStateRef<T, Shallow extends boolean = false> = Shallow extends true ? ShallowStateRef<T> : DeepStateRef<T>;
10
+ /** useState 的返回元组:[状态引用, 写入函数] */
11
+ export type UseStateReturn<T, Shallow extends boolean = false> = [
12
+ UseStateRef<T, Shallow>,
13
+ (newVal: T) => boolean
14
+ ];
15
+ /** useState 的配置项 */
16
+ export interface UseStateConfig<T, Shallow extends boolean = false> {
17
+ /** 是否使用浅层引用(true 时不做深层响应式转换) */
18
+ shallow?: Shallow;
19
+ /** 是否启用差异比较,相等则跳过写入 */
20
+ diff?: boolean;
21
+ /** 自定义相等判定,返回真表示新旧值相等、无需写入 */
22
+ compare?: (oldVal: UseStateRef<T, Shallow>['value'], newVal: T) => boolean;
23
+ /** 写入前的拦截钩子,可返回加工后的新值 */
24
+ beforeSet?: (newVal: T) => T;
25
+ }
26
+ /**
27
+ * 创建带差异比较与写入拦截能力的响应式状态
28
+ * @param source 初始值来源,支持值、Ref 或 getter
29
+ * @param config 配置项;shallow 为 true 时返回浅层引用
30
+ * @returns 元组 [状态引用, 写入函数],写入函数返回是否发生实际写入
31
+ */
32
+ export declare function useState<T>(source: MaybeRefOrGetter<T>, config: UseStateConfig<T, true> & {
33
+ shallow: true;
34
+ }): UseStateReturn<T, true>;
35
+ export declare function useState<T>(source: MaybeRefOrGetter<T>, config?: UseStateConfig<T, false>): UseStateReturn<T, false>;
36
+ export declare function useState<T>(source: MaybeRefOrGetter<T>, config?: UseStateConfig<T, boolean>): UseStateReturn<T, boolean>;
37
+ export {};
@@ -0,0 +1,28 @@
1
+ /** 定时器回调,可同步返回,也可返回 thenable 表示异步 */
2
+ export type Callback = () => void | PromiseLike<void>;
3
+ /** 定时器控制器 */
4
+ export interface ControlFunctions {
5
+ /** 永久停止并释放定时器,不可再启动 */
6
+ stop: () => void;
7
+ /** 暂停计时,保持已消耗的逻辑时间 */
8
+ pause: () => void;
9
+ /** 从暂停处恢复计时 */
10
+ start: () => void;
11
+ }
12
+ /** 定时器配置项 */
13
+ export interface RafTimerOptions {
14
+ /** 计时基准:waitAfterCallback 回调完成后计时,ignoreCallbackTime 忽略回调耗时 */
15
+ type?: 'waitAfterCallback' | 'ignoreCallbackTime';
16
+ /** 循环方式:true 无限循环、false 仅一次、数字表示循环次数 */
17
+ loop?: boolean | number;
18
+ /** 回调同步抛错或返回的 thenable 拒绝时的处理器 */
19
+ onError?: (error: unknown) => void | PromiseLike<void>;
20
+ }
21
+ /**
22
+ * 创建基于动画帧的定时器
23
+ * @param callback 每帧触发的回调
24
+ * @param interval 触发间隔(毫秒),缺省按 60fps 计算
25
+ * @param options 定时器配置项
26
+ * @returns 含 stop / pause / start 的控制器
27
+ */
28
+ export declare function useRafTimer(callback: Callback, interval?: number, options?: RafTimerOptions): ControlFunctions;
@@ -0,0 +1,80 @@
1
+ /** @file 通用类型判断与安全执行工具函数集合 */
2
+ /**
3
+ * 判断值是否为函数
4
+ * @param value 待检测的值
5
+ * @returns 值为函数时返回真
6
+ */
7
+ export declare function isFunction(value: unknown): value is (...args: never[]) => unknown;
8
+ /**
9
+ * 判断传入值是否为函数,是则带参执行并返回结果
10
+ * @param fn 可能为空的目标函数
11
+ * @param args 传给目标函数的参数列表
12
+ * @returns 目标函数执行结果;非函数或执行抛错时返回 undefined
13
+ */
14
+ export declare function isFunctionAndExec<Args extends unknown[], Result>(fn: ((...args: Args) => Result) | null | undefined, ...args: Args): Result | undefined;
15
+ /**
16
+ * 判断值是否为 Promise 风格对象(含 thenable)
17
+ * @param obj 待检测的值
18
+ * @returns 值可被 then 消费时返回真
19
+ */
20
+ export declare function isPromise<T = unknown>(obj: unknown): obj is PromiseLike<T>;
21
+ /**
22
+ * 判断值是否为 Error 实例
23
+ * @param value 待检测的值
24
+ * @returns 值为 Error 实例时返回真
25
+ */
26
+ export declare function isError(value: unknown): value is Error;
27
+ /**
28
+ * 判断值是否为布尔类型
29
+ * @param value 待检测的值
30
+ * @returns 值为布尔时返回真
31
+ */
32
+ export declare function isBoolean(value: unknown): value is boolean;
33
+ /**
34
+ * 判断值是否为整数(沿用既有的仅整数语义)
35
+ * @param value 待检测的值
36
+ * @returns 值为整数时返回真,浮点数返回假
37
+ */
38
+ export declare function isNumber(value: unknown): value is number;
39
+ /**
40
+ * 判断字符串是否由纯数字组成(不含符号、小数点)
41
+ * @param str 待检测的字符串
42
+ * @returns 全部字符均为数字时返回真
43
+ */
44
+ export declare function isPureNumberString(str: string): boolean;
45
+ /**
46
+ * 判断值是否为字符串
47
+ * @param value 待检测的值
48
+ * @returns 值为字符串时返回真
49
+ */
50
+ export declare function isString(value: unknown): value is string;
51
+ /**
52
+ * 判断值是否为非空字符串
53
+ * @param value 待检测的值
54
+ * @returns 值为字符串且长度大于零时返回真
55
+ */
56
+ export declare function strHasContent(value: unknown): value is string;
57
+ /**
58
+ * 判断值是否为普通对象(排除数组、null 等)
59
+ * @param value 待检测的值
60
+ * @returns 值为 [object Object] 形态的普通对象时返回真
61
+ */
62
+ export declare function isObject(value: unknown): value is Record<string, unknown>;
63
+ /**
64
+ * 判断值是否为非空普通对象
65
+ * @param value 待检测的值
66
+ * @returns 值为普通对象且至少含一个自有键时返回真
67
+ */
68
+ export declare function objHasContent(value: unknown): value is Record<string, unknown>;
69
+ /**
70
+ * 判断值是否为数组
71
+ * @param value 待检测的值
72
+ * @returns 值为数组时返回真
73
+ */
74
+ export declare function isArray(value: unknown): value is unknown[];
75
+ /**
76
+ * 判断值是否为非空数组
77
+ * @param value 待检测的值
78
+ * @returns 值为数组且长度大于零时返回真
79
+ */
80
+ export declare function arrHasContent(value: unknown): value is unknown[];