@fast-china/utils 1.0.38 → 2.0.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/CHANGELOG.md +48 -0
- package/CONTRIBUTING.md +87 -0
- package/README.md +109 -50
- package/README.zh.md +109 -50
- package/SECURITY.md +46 -0
- package/dist/array/index.d.mts +87 -0
- package/dist/array/index.mjs +161 -0
- package/dist/array/index.mjs.map +1 -0
- package/dist/async/index.d.mts +146 -0
- package/dist/async/index.mjs +336 -0
- package/dist/async/index.mjs.map +1 -0
- package/dist/base64/index.d.mts +105 -0
- package/dist/base64/index.mjs +427 -0
- package/dist/base64/index.mjs.map +1 -0
- package/dist/color/index.d.mts +90 -0
- package/dist/color/index.mjs +178 -0
- package/dist/color/index.mjs.map +1 -0
- package/dist/crypto/index.d.mts +326 -0
- package/dist/crypto/index.mjs +843 -0
- package/dist/crypto/index.mjs.map +1 -0
- package/dist/date/index.d.mts +191 -0
- package/dist/date/index.mjs +383 -0
- package/dist/date/index.mjs.map +1 -0
- package/dist/dom/style.d.mts +30 -0
- package/dist/dom/style.mjs +74 -0
- package/dist/dom/style.mjs.map +1 -0
- package/dist/env/index.d.mts +63 -0
- package/dist/env/index.mjs +97 -0
- package/dist/env/index.mjs.map +1 -0
- package/dist/identity/index.d.mts +78 -0
- package/dist/identity/index.mjs +87 -0
- package/dist/identity/index.mjs.map +1 -0
- package/dist/index.d.mts +24 -0
- package/dist/index.global.min.js +3 -2
- package/dist/index.global.min.js.map +1 -1
- package/dist/index.mjs +23 -0
- package/dist/internal/text.mjs +36 -0
- package/dist/internal/text.mjs.map +1 -0
- package/dist/logger/index.d.mts +87 -0
- package/dist/logger/index.mjs +124 -0
- package/dist/logger/index.mjs.map +1 -0
- package/dist/number/index.d.mts +89 -0
- package/dist/number/index.mjs +215 -0
- package/dist/number/index.mjs.map +1 -0
- package/dist/object/index.d.mts +76 -0
- package/dist/object/index.mjs +134 -0
- package/dist/object/index.mjs.map +1 -0
- package/dist/storage/index.d.mts +107 -0
- package/dist/storage/index.mjs +327 -0
- package/dist/storage/index.mjs.map +1 -0
- package/dist/string/index.d.mts +130 -0
- package/dist/string/index.mjs +275 -0
- package/dist/string/index.mjs.map +1 -0
- package/dist/vue/emits.d.mts +24 -0
- package/dist/vue/emits.mjs +47 -0
- package/dist/vue/emits.mjs.map +1 -0
- package/dist/vue/expose.d.mts +12 -0
- package/dist/vue/expose.mjs +16 -0
- package/dist/vue/expose.mjs.map +1 -0
- package/dist/vue/func.d.mts +14 -0
- package/dist/vue/func.mjs +16 -0
- package/dist/vue/func.mjs.map +1 -0
- package/dist/vue/index.d.mts +9 -0
- package/dist/vue/install.d.mts +51 -0
- package/dist/vue/install.mjs +123 -0
- package/dist/vue/install.mjs.map +1 -0
- package/dist/vue/props.d.mts +23 -0
- package/dist/vue/props.mjs +41 -0
- package/dist/vue/props.mjs.map +1 -0
- package/dist/vue/render.d.mts +12 -0
- package/dist/vue/render.mjs +17 -0
- package/dist/vue/render.mjs.map +1 -0
- package/dist/vue/slots.d.mts +19 -0
- package/dist/vue/slots.mjs +13 -0
- package/dist/vue/slots.mjs.map +1 -0
- package/dist/vue/with.d.mts +12 -0
- package/dist/vue/with.mjs +15 -0
- package/dist/vue/with.mjs.map +1 -0
- package/docs/API.md +112 -0
- package/docs/API.zh-CN.md +112 -0
- package/docs/DEVELOPMENT_RELEASE.zh-CN.md +65 -0
- package/docs/RUNTIME_CONTRACT.md +37 -0
- package/package.json +63 -73
- package/dist/index.global.js +0 -14500
- package/dist/index.global.js.map +0 -1
- package/es/array/index.d.ts +0 -19
- package/es/array/index.mjs +0 -2
- package/es/array/index.mjs.map +0 -1
- package/es/base64/index.d.ts +0 -21
- package/es/base64/index.mjs +0 -2
- package/es/base64/index.mjs.map +0 -1
- package/es/click/index.d.ts +0 -33
- package/es/click/index.mjs +0 -2
- package/es/click/index.mjs.map +0 -1
- package/es/color/index.d.ts +0 -33
- package/es/color/index.mjs +0 -2
- package/es/color/index.mjs.map +0 -1
- package/es/console/index.d.ts +0 -31
- package/es/console/index.mjs +0 -2
- package/es/console/index.mjs.map +0 -1
- package/es/crypto/index.d.ts +0 -46
- package/es/crypto/index.mjs +0 -2
- package/es/crypto/index.mjs.map +0 -1
- package/es/date/index.d.ts +0 -44
- package/es/date/index.mjs +0 -2
- package/es/date/index.mjs.map +0 -1
- package/es/dom/index.d.ts +0 -1
- package/es/dom/index.mjs +0 -2
- package/es/dom/index.mjs.map +0 -1
- package/es/dom/style.d.ts +0 -12
- package/es/dom/style.mjs +0 -2
- package/es/dom/style.mjs.map +0 -1
- package/es/env/index.d.ts +0 -25
- package/es/env/index.mjs +0 -2
- package/es/env/index.mjs.map +0 -1
- package/es/error/index.d.ts +0 -3
- package/es/error/index.mjs +0 -2
- package/es/error/index.mjs.map +0 -1
- package/es/identity/index.d.ts +0 -14
- package/es/identity/index.mjs +0 -2
- package/es/identity/index.mjs.map +0 -1
- package/es/index.d.ts +0 -15
- package/es/index.es.d.ts +0 -2
- package/es/index.mjs +0 -2
- package/es/index.mjs.map +0 -1
- package/es/object/index.d.ts +0 -13
- package/es/object/index.mjs +0 -2
- package/es/object/index.mjs.map +0 -1
- package/es/storage/index.d.ts +0 -96
- package/es/storage/index.mjs +0 -2
- package/es/storage/index.mjs.map +0 -1
- package/es/string/index.d.ts +0 -114
- package/es/string/index.mjs +0 -2
- package/es/string/index.mjs.map +0 -1
- package/es/vue/emits.d.ts +0 -8
- package/es/vue/emits.mjs +0 -2
- package/es/vue/emits.mjs.map +0 -1
- package/es/vue/expose.d.ts +0 -4
- package/es/vue/expose.mjs +0 -2
- package/es/vue/expose.mjs.map +0 -1
- package/es/vue/func.d.ts +0 -6
- package/es/vue/func.mjs +0 -2
- package/es/vue/func.mjs.map +0 -1
- package/es/vue/index.d.ts +0 -8
- package/es/vue/index.mjs +0 -2
- package/es/vue/index.mjs.map +0 -1
- package/es/vue/install.d.ts +0 -5
- package/es/vue/install.mjs +0 -2
- package/es/vue/install.mjs.map +0 -1
- package/es/vue/props.d.ts +0 -9
- package/es/vue/props.mjs +0 -2
- package/es/vue/props.mjs.map +0 -1
- package/es/vue/slots.d.ts +0 -11
- package/es/vue/slots.mjs +0 -2
- package/es/vue/slots.mjs.map +0 -1
- package/es/vue/useRender.d.ts +0 -6
- package/es/vue/useRender.mjs +0 -2
- package/es/vue/useRender.mjs.map +0 -1
- package/es/vue/with.d.ts +0 -5
- package/es/vue/with.mjs +0 -2
- package/es/vue/with.mjs.map +0 -1
- package/lib/array/index.d.ts +0 -19
- package/lib/array/index.js +0 -2
- package/lib/array/index.js.map +0 -1
- package/lib/base64/index.d.ts +0 -21
- package/lib/base64/index.js +0 -2
- package/lib/base64/index.js.map +0 -1
- package/lib/click/index.d.ts +0 -33
- package/lib/click/index.js +0 -2
- package/lib/click/index.js.map +0 -1
- package/lib/color/index.d.ts +0 -33
- package/lib/color/index.js +0 -2
- package/lib/color/index.js.map +0 -1
- package/lib/console/index.d.ts +0 -31
- package/lib/console/index.js +0 -2
- package/lib/console/index.js.map +0 -1
- package/lib/crypto/index.d.ts +0 -46
- package/lib/crypto/index.js +0 -2
- package/lib/crypto/index.js.map +0 -1
- package/lib/date/index.d.ts +0 -44
- package/lib/date/index.js +0 -2
- package/lib/date/index.js.map +0 -1
- package/lib/dom/index.d.ts +0 -1
- package/lib/dom/index.js +0 -2
- package/lib/dom/index.js.map +0 -1
- package/lib/dom/style.d.ts +0 -12
- package/lib/dom/style.js +0 -2
- package/lib/dom/style.js.map +0 -1
- package/lib/env/index.d.ts +0 -25
- package/lib/env/index.js +0 -2
- package/lib/env/index.js.map +0 -1
- package/lib/error/index.d.ts +0 -3
- package/lib/error/index.js +0 -2
- package/lib/error/index.js.map +0 -1
- package/lib/identity/index.d.ts +0 -14
- package/lib/identity/index.js +0 -2
- package/lib/identity/index.js.map +0 -1
- package/lib/index.d.ts +0 -15
- package/lib/index.es.d.ts +0 -2
- package/lib/index.js +0 -2
- package/lib/index.js.map +0 -1
- package/lib/object/index.d.ts +0 -13
- package/lib/object/index.js +0 -2
- package/lib/object/index.js.map +0 -1
- package/lib/storage/index.d.ts +0 -96
- package/lib/storage/index.js +0 -2
- package/lib/storage/index.js.map +0 -1
- package/lib/string/index.d.ts +0 -114
- package/lib/string/index.js +0 -2
- package/lib/string/index.js.map +0 -1
- package/lib/vue/emits.d.ts +0 -8
- package/lib/vue/emits.js +0 -2
- package/lib/vue/emits.js.map +0 -1
- package/lib/vue/expose.d.ts +0 -4
- package/lib/vue/expose.js +0 -2
- package/lib/vue/expose.js.map +0 -1
- package/lib/vue/func.d.ts +0 -6
- package/lib/vue/func.js +0 -2
- package/lib/vue/func.js.map +0 -1
- package/lib/vue/index.d.ts +0 -8
- package/lib/vue/index.js +0 -2
- package/lib/vue/index.js.map +0 -1
- package/lib/vue/install.d.ts +0 -5
- package/lib/vue/install.js +0 -2
- package/lib/vue/install.js.map +0 -1
- package/lib/vue/props.d.ts +0 -9
- package/lib/vue/props.js +0 -2
- package/lib/vue/props.js.map +0 -1
- package/lib/vue/slots.d.ts +0 -11
- package/lib/vue/slots.js +0 -2
- package/lib/vue/slots.js.map +0 -1
- package/lib/vue/useRender.d.ts +0 -6
- package/lib/vue/useRender.js +0 -2
- package/lib/vue/useRender.js.map +0 -1
- package/lib/vue/with.d.ts +0 -5
- package/lib/vue/with.js +0 -2
- package/lib/vue/with.js.map +0 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/vue/func.ts
|
|
2
|
+
/**
|
|
3
|
+
* 统一执行同步或异步函数,异常保持原样向调用方传播。
|
|
4
|
+
*
|
|
5
|
+
* @param function_ - 可选的待执行函数。
|
|
6
|
+
* @param arguments_ - 原样传入函数的参数。
|
|
7
|
+
* @returns 函数结果;未传函数时返回 `undefined`。
|
|
8
|
+
*/
|
|
9
|
+
async function callOptionalFunction(function_, ...arguments_) {
|
|
10
|
+
if (function_ === null || function_ === void 0) return void 0;
|
|
11
|
+
return await function_(...arguments_);
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { callOptionalFunction };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=func.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"func.mjs","names":[],"sources":["../../src/vue/func.ts"],"sourcesContent":["/** 可同步或异步返回结果的函数。 */\nexport type AwaitableFunction<Arguments extends readonly unknown[], Result> = (...arguments_: Arguments) => Result | PromiseLike<Result>;\n\n/**\n * 统一执行同步或异步函数,异常保持原样向调用方传播。\n *\n * @param function_ - 可选的待执行函数。\n * @param arguments_ - 原样传入函数的参数。\n * @returns 函数结果;未传函数时返回 `undefined`。\n */\nexport async function callOptionalFunction<Arguments extends readonly unknown[], Result>(\n\tfunction_: AwaitableFunction<Arguments, Result> | null | undefined,\n\t...arguments_: Arguments\n): Promise<Awaited<Result> | undefined> {\n\tif (function_ === null || function_ === undefined) return undefined;\n\treturn await function_(...arguments_);\n}\n"],"mappings":";;;;;;;;AAUA,eAAsB,qBACrB,WACA,GAAG,YACoC;CACvC,IAAI,cAAc,QAAQ,cAAc,KAAA,GAAW,OAAO,KAAA;CAC1D,OAAO,MAAM,UAAU,GAAG,UAAU;AACrC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EmitHandlers, useEmits } from "./emits.mjs";
|
|
2
|
+
import { useExpose } from "./expose.mjs";
|
|
3
|
+
import { AwaitableFunction, callOptionalFunction } from "./func.mjs";
|
|
4
|
+
import { Installable, TSXWithInstall, VueInstallValue, withInstall, withInstallDirective, withNoopInstall } from "./install.mjs";
|
|
5
|
+
import { definePropType, useProps } from "./props.mjs";
|
|
6
|
+
import { useRender } from "./render.mjs";
|
|
7
|
+
import { TypedSlots, TypedSlotsDeclaration, makeSlots } from "./slots.mjs";
|
|
8
|
+
import { withDefineType } from "./with.mjs";
|
|
9
|
+
export { AwaitableFunction, EmitHandlers, Installable, TSXWithInstall, TypedSlots, TypedSlotsDeclaration, VueInstallValue, callOptionalFunction, definePropType, makeSlots, useEmits, useExpose, useProps, useRender, withDefineType, withInstall, withInstallDirective, withNoopInstall };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { App } from "vue";
|
|
2
|
+
//#region src/vue/install.d.ts
|
|
3
|
+
/** Vue 组件对象、函数组件或指令对象可接受的最小结构类型。 */
|
|
4
|
+
type VueInstallValue = object | ((...arguments_: never[]) => unknown);
|
|
5
|
+
/** 为 Vue 组件或指令附加供 Vue 3 `app.use()` 调用的安装能力。 */
|
|
6
|
+
type Installable<Value> = Value & {
|
|
7
|
+
/**
|
|
8
|
+
* 把当前组件或指令安装到 Vue 3 App。
|
|
9
|
+
* @param app - Vue 3 App 实例。
|
|
10
|
+
*/
|
|
11
|
+
install: (app: App) => void;
|
|
12
|
+
};
|
|
13
|
+
/** TSX 组件安装类型;与 {@link Installable} 保持同一运行时契约。 */
|
|
14
|
+
type TSXWithInstall<Value> = Installable<Value>;
|
|
15
|
+
/**
|
|
16
|
+
* 为主组件附加 Vue 3 `app.use()` 安装能力。
|
|
17
|
+
*
|
|
18
|
+
* @remarks 函数会直接为 `main` 定义附属组件属性和 `install`。所有组件名称、附属属性
|
|
19
|
+
* 冲突会在修改 `main` 前完成校验;安装到 App 时也会先预检全部全局名称,再统一注册。
|
|
20
|
+
* @param main - 具有非空 `name` 的组件。
|
|
21
|
+
* @param extras - 同时注册并以可枚举属性挂到主组件的附属组件映射。
|
|
22
|
+
* @returns 原始 `main` 引用,并附加类型化的 `install` 与 `extras` 属性。
|
|
23
|
+
* @throws `TypeError` 当组件缺少合法名称、已有 `install`、附属键或名称发生冲突。
|
|
24
|
+
* @throws `Error` 当 App 中同名位置已经注册其他组件。
|
|
25
|
+
*/
|
|
26
|
+
declare function withInstall<Main extends VueInstallValue, Extras extends Record<string, VueInstallValue> = Record<never, never>>(main: Main, extras?: Extras): Installable<Main> & Extras;
|
|
27
|
+
/**
|
|
28
|
+
* 为不需要单独注册的附属组件附加空安装函数。
|
|
29
|
+
*
|
|
30
|
+
* @remarks 适用于只能作为主组件附属属性使用、但仍需满足 Vue Plugin 类型的组件。
|
|
31
|
+
* 函数直接修改并返回传入组件,不会向 Vue 3 App 注册内容。
|
|
32
|
+
* @param component - 尚未定义或继承 `install` 属性的组件。
|
|
33
|
+
* @returns 原组件引用及无副作用的 `install` 方法。
|
|
34
|
+
* @throws `TypeError` 当组件自身或原型链已经存在 `install`。
|
|
35
|
+
*/
|
|
36
|
+
declare function withNoopInstall<Value extends VueInstallValue>(component: Value): TSXWithInstall<Value>;
|
|
37
|
+
/**
|
|
38
|
+
* 为 Vue 3 指令附加插件安装能力。
|
|
39
|
+
*
|
|
40
|
+
* @remarks 函数直接修改并返回指令。安装时重复注册同一引用保持幂等,不会覆盖同名的
|
|
41
|
+
* 其他指令。名称只传给 `directive()`,不得包含 `v-` 前缀。
|
|
42
|
+
* @param directive - 尚未定义或继承 `install` 属性的 Vue 指令对象。
|
|
43
|
+
* @param name - 非空、无空白且不以 `v-` 开头的全局指令名。
|
|
44
|
+
* @returns 原指令引用及 Vue Plugin `install` 方法。
|
|
45
|
+
* @throws `TypeError` 当名称非法、指令已有 `install`,或安装目标无效。
|
|
46
|
+
* @throws `Error` 当 App 中同名位置已经注册其他指令。
|
|
47
|
+
*/
|
|
48
|
+
declare function withInstallDirective<Value extends VueInstallValue>(directive: Value, name: string): Installable<Value>;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { Installable, TSXWithInstall, VueInstallValue, withInstall, withInstallDirective, withNoopInstall };
|
|
51
|
+
//# sourceMappingURL=install.d.mts.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
//#region src/vue/install.ts
|
|
2
|
+
/**
|
|
3
|
+
* 校验 Vue 3 插件安装目标。
|
|
4
|
+
*
|
|
5
|
+
* @param value - Vue 3 App 实例。
|
|
6
|
+
* @returns 只包含组件和指令注册能力的 App。
|
|
7
|
+
* @throws `TypeError` 当目标不是对象或缺少 `component`、`directive` 方法。
|
|
8
|
+
*/
|
|
9
|
+
const assertApp = (value) => {
|
|
10
|
+
if (typeof value !== "object" || value === null) throw new TypeError("Vue plugin installation requires a Vue 3 App.");
|
|
11
|
+
const app = value;
|
|
12
|
+
if (typeof app.component !== "function" || typeof app.directive !== "function") throw new TypeError("Vue plugin installation requires component() and directive() registration methods.");
|
|
13
|
+
return app;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* 提取组件的全局注册名称。
|
|
17
|
+
*
|
|
18
|
+
* @param component - 待注册组件。
|
|
19
|
+
* @returns 经过校验的显式名称。
|
|
20
|
+
* @throws `TypeError` 当组件没有非空字符串名称,或名称包含空白。
|
|
21
|
+
*/
|
|
22
|
+
const getComponentName = (component) => {
|
|
23
|
+
const name = component.name;
|
|
24
|
+
if (typeof name !== "string" || name.length === 0 || /\s/u.test(name)) throw new TypeError("Installable Vue components must expose a non-empty name without whitespace.");
|
|
25
|
+
return name;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* 预检单个组件注册。
|
|
29
|
+
*
|
|
30
|
+
* @remarks 先读取同名组件并完成冲突判断,再返回延迟执行动作;调用方可以在所有组件预检通过后统一提交。
|
|
31
|
+
* @param app - 已校验的 Vue 3 App 注册目标。
|
|
32
|
+
* @param component - 待注册组件。
|
|
33
|
+
* @returns 已校验的组件引用、名称和目标中是否已经存在同一引用。
|
|
34
|
+
* @throws `Error` 当同名位置已由其他组件占用。
|
|
35
|
+
*/
|
|
36
|
+
const prepareComponentRegistration = (app, component) => {
|
|
37
|
+
const name = getComponentName(component);
|
|
38
|
+
const existing = app.component(name);
|
|
39
|
+
if (existing !== void 0 && existing !== component) throw new Error(`Vue component name "${name}" is already registered by another component.`);
|
|
40
|
+
return {
|
|
41
|
+
component,
|
|
42
|
+
name,
|
|
43
|
+
registered: existing === component
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* 为主组件附加 Vue 3 `app.use()` 安装能力。
|
|
48
|
+
*
|
|
49
|
+
* @remarks 函数会直接为 `main` 定义附属组件属性和 `install`。所有组件名称、附属属性
|
|
50
|
+
* 冲突会在修改 `main` 前完成校验;安装到 App 时也会先预检全部全局名称,再统一注册。
|
|
51
|
+
* @param main - 具有非空 `name` 的组件。
|
|
52
|
+
* @param extras - 同时注册并以可枚举属性挂到主组件的附属组件映射。
|
|
53
|
+
* @returns 原始 `main` 引用,并附加类型化的 `install` 与 `extras` 属性。
|
|
54
|
+
* @throws `TypeError` 当组件缺少合法名称、已有 `install`、附属键或名称发生冲突。
|
|
55
|
+
* @throws `Error` 当 App 中同名位置已经注册其他组件。
|
|
56
|
+
*/
|
|
57
|
+
function withInstall(main, extras) {
|
|
58
|
+
const componentNames = /* @__PURE__ */ new Set([getComponentName(main)]);
|
|
59
|
+
if ("install" in Object(main)) throw new TypeError("The Vue component already defines an install property.");
|
|
60
|
+
const extraEntries = Object.entries(extras ?? {});
|
|
61
|
+
if (extras !== void 0 && Object.getOwnPropertySymbols(extras).some((key) => Object.prototype.propertyIsEnumerable.call(extras, key))) throw new TypeError("Vue component extras must use string property names.");
|
|
62
|
+
for (const [key, component] of extraEntries) {
|
|
63
|
+
const componentName = getComponentName(component);
|
|
64
|
+
if (componentNames.has(componentName)) throw new TypeError(`Vue component name "${componentName}" is registered more than once.`);
|
|
65
|
+
componentNames.add(componentName);
|
|
66
|
+
if (key === "install" || key in Object(main)) throw new TypeError(`Vue component extra "${key}" would overwrite a property on the main component.`);
|
|
67
|
+
}
|
|
68
|
+
const installable = main;
|
|
69
|
+
for (const [key, component] of extraEntries) Object.defineProperty(installable, key, {
|
|
70
|
+
configurable: true,
|
|
71
|
+
enumerable: true,
|
|
72
|
+
value: component,
|
|
73
|
+
writable: true
|
|
74
|
+
});
|
|
75
|
+
installable.install = (value) => {
|
|
76
|
+
const app = assertApp(value);
|
|
77
|
+
const registrations = [main, ...extraEntries.map(([, component]) => component)].map((component) => prepareComponentRegistration(app, component));
|
|
78
|
+
for (const registration of registrations) if (!registration.registered) app.component(registration.name, registration.component);
|
|
79
|
+
};
|
|
80
|
+
return installable;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 为不需要单独注册的附属组件附加空安装函数。
|
|
84
|
+
*
|
|
85
|
+
* @remarks 适用于只能作为主组件附属属性使用、但仍需满足 Vue Plugin 类型的组件。
|
|
86
|
+
* 函数直接修改并返回传入组件,不会向 Vue 3 App 注册内容。
|
|
87
|
+
* @param component - 尚未定义或继承 `install` 属性的组件。
|
|
88
|
+
* @returns 原组件引用及无副作用的 `install` 方法。
|
|
89
|
+
* @throws `TypeError` 当组件自身或原型链已经存在 `install`。
|
|
90
|
+
*/
|
|
91
|
+
function withNoopInstall(component) {
|
|
92
|
+
if ("install" in Object(component)) throw new TypeError("The Vue component already defines an install property.");
|
|
93
|
+
const installable = component;
|
|
94
|
+
installable.install = () => void 0;
|
|
95
|
+
return installable;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 为 Vue 3 指令附加插件安装能力。
|
|
99
|
+
*
|
|
100
|
+
* @remarks 函数直接修改并返回指令。安装时重复注册同一引用保持幂等,不会覆盖同名的
|
|
101
|
+
* 其他指令。名称只传给 `directive()`,不得包含 `v-` 前缀。
|
|
102
|
+
* @param directive - 尚未定义或继承 `install` 属性的 Vue 指令对象。
|
|
103
|
+
* @param name - 非空、无空白且不以 `v-` 开头的全局指令名。
|
|
104
|
+
* @returns 原指令引用及 Vue Plugin `install` 方法。
|
|
105
|
+
* @throws `TypeError` 当名称非法、指令已有 `install`,或安装目标无效。
|
|
106
|
+
* @throws `Error` 当 App 中同名位置已经注册其他指令。
|
|
107
|
+
*/
|
|
108
|
+
function withInstallDirective(directive, name) {
|
|
109
|
+
if (name.length === 0 || /\s/u.test(name) || name.startsWith("v-")) throw new TypeError("Installable Vue directives require a name without whitespace or a v- prefix.");
|
|
110
|
+
if ("install" in Object(directive)) throw new TypeError("The Vue directive already defines an install property.");
|
|
111
|
+
const installable = directive;
|
|
112
|
+
installable.install = (value) => {
|
|
113
|
+
const app = assertApp(value);
|
|
114
|
+
const existing = app.directive(name);
|
|
115
|
+
if (existing !== void 0 && existing !== directive) throw new Error(`Vue directive name "${name}" is already registered by another directive.`);
|
|
116
|
+
if (existing !== directive) app.directive(name, directive);
|
|
117
|
+
};
|
|
118
|
+
return installable;
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
export { withInstall, withInstallDirective, withNoopInstall };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=install.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.mjs","names":[],"sources":["../../src/vue/install.ts"],"sourcesContent":["import type { App } from \"vue\";\n\n/** Vue 组件对象、函数组件或指令对象可接受的最小结构类型。 */\nexport type VueInstallValue = object | ((...arguments_: never[]) => unknown);\n\n/** 为 Vue 组件或指令附加供 Vue 3 `app.use()` 调用的安装能力。 */\nexport type Installable<Value> = Value & {\n\t/**\n\t * 把当前组件或指令安装到 Vue 3 App。\n\t * @param app - Vue 3 App 实例。\n\t */\n\tinstall: (app: App) => void;\n};\n\n/** TSX 组件安装类型;与 {@link Installable} 保持同一运行时契约。 */\nexport type TSXWithInstall<Value> = Installable<Value>;\n\n/** 组件、指令注册所需的 Vue 3 App 能力。 */\ninterface VueAppRegistrationTarget {\n\t/**\n\t * 读取或注册全局组件。\n\t *\n\t * @param name - 全局组件名。\n\t * @param component - 注册时传入的组件;省略时读取现有组件。\n\t * @returns Vue App 返回的现有组件、注册结果或 App 自身。\n\t */\n\tcomponent: (name: string, component?: unknown) => unknown;\n\t/**\n\t * 读取或注册全局指令。\n\t *\n\t * @param name - 不带 `v-` 的全局指令名。\n\t * @param directive - 注册时传入的指令;省略时读取现有指令。\n\t * @returns Vue App 返回的现有指令、注册结果或 App 自身。\n\t */\n\tdirective: (name: string, directive?: unknown) => unknown;\n}\n\n/**\n * 校验 Vue 3 插件安装目标。\n *\n * @param value - Vue 3 App 实例。\n * @returns 只包含组件和指令注册能力的 App。\n * @throws `TypeError` 当目标不是对象或缺少 `component`、`directive` 方法。\n */\nconst assertApp = (value: App): VueAppRegistrationTarget => {\n\tif (typeof value !== \"object\" || value === null) {\n\t\tthrow new TypeError(\"Vue plugin installation requires a Vue 3 App.\");\n\t}\n\tconst app = value as unknown as Partial<VueAppRegistrationTarget>;\n\tif (typeof app.component !== \"function\" || typeof app.directive !== \"function\") {\n\t\tthrow new TypeError(\"Vue plugin installation requires component() and directive() registration methods.\");\n\t}\n\treturn app as VueAppRegistrationTarget;\n};\n\n/**\n * 提取组件的全局注册名称。\n *\n * @param component - 待注册组件。\n * @returns 经过校验的显式名称。\n * @throws `TypeError` 当组件没有非空字符串名称,或名称包含空白。\n */\nconst getComponentName = (component: VueInstallValue): string => {\n\tconst name = (component as { name?: unknown }).name;\n\tif (typeof name !== \"string\" || name.length === 0 || /\\s/u.test(name)) {\n\t\tthrow new TypeError(\"Installable Vue components must expose a non-empty name without whitespace.\");\n\t}\n\treturn name;\n};\n\n/** 预检完成、可以无失败注册的组件动作。 */\ninterface ComponentRegistration {\n\t/** 已校验的组件引用。 */\n\tcomponent: VueInstallValue;\n\t/** 已校验的组件名称。 */\n\tname: string;\n\t/** 目标中是否已经注册了完全相同的组件引用。 */\n\tregistered: boolean;\n}\n\n/**\n * 预检单个组件注册。\n *\n * @remarks 先读取同名组件并完成冲突判断,再返回延迟执行动作;调用方可以在所有组件预检通过后统一提交。\n * @param app - 已校验的 Vue 3 App 注册目标。\n * @param component - 待注册组件。\n * @returns 已校验的组件引用、名称和目标中是否已经存在同一引用。\n * @throws `Error` 当同名位置已由其他组件占用。\n */\nconst prepareComponentRegistration = (app: VueAppRegistrationTarget, component: VueInstallValue): ComponentRegistration => {\n\tconst name = getComponentName(component);\n\tconst existing = app.component(name);\n\tif (existing !== undefined && existing !== component) {\n\t\tthrow new Error(`Vue component name \"${name}\" is already registered by another component.`);\n\t}\n\treturn { component, name, registered: existing === component };\n};\n\n/**\n * 为主组件附加 Vue 3 `app.use()` 安装能力。\n *\n * @remarks 函数会直接为 `main` 定义附属组件属性和 `install`。所有组件名称、附属属性\n * 冲突会在修改 `main` 前完成校验;安装到 App 时也会先预检全部全局名称,再统一注册。\n * @param main - 具有非空 `name` 的组件。\n * @param extras - 同时注册并以可枚举属性挂到主组件的附属组件映射。\n * @returns 原始 `main` 引用,并附加类型化的 `install` 与 `extras` 属性。\n * @throws `TypeError` 当组件缺少合法名称、已有 `install`、附属键或名称发生冲突。\n * @throws `Error` 当 App 中同名位置已经注册其他组件。\n */\nexport function withInstall<Main extends VueInstallValue, Extras extends Record<string, VueInstallValue> = Record<never, never>>(\n\tmain: Main,\n\textras?: Extras\n): Installable<Main> & Extras {\n\tconst componentNames = new Set([getComponentName(main)]);\n\tif (\"install\" in Object(main)) throw new TypeError(\"The Vue component already defines an install property.\");\n\tconst extraEntries = Object.entries(extras ?? {});\n\tif (extras !== undefined && Object.getOwnPropertySymbols(extras).some((key) => Object.prototype.propertyIsEnumerable.call(extras, key))) {\n\t\tthrow new TypeError(\"Vue component extras must use string property names.\");\n\t}\n\tfor (const [key, component] of extraEntries) {\n\t\tconst componentName = getComponentName(component);\n\t\tif (componentNames.has(componentName)) throw new TypeError(`Vue component name \"${componentName}\" is registered more than once.`);\n\t\tcomponentNames.add(componentName);\n\t\tif (key === \"install\" || key in Object(main)) {\n\t\t\tthrow new TypeError(`Vue component extra \"${key}\" would overwrite a property on the main component.`);\n\t\t}\n\t}\n\tconst installable = main as Installable<Main> & Extras;\n\tfor (const [key, component] of extraEntries) {\n\t\tObject.defineProperty(installable, key, { configurable: true, enumerable: true, value: component, writable: true });\n\t}\n\tinstallable.install = (value: App): void => {\n\t\tconst app = assertApp(value);\n\t\t// 先完成全部冲突检查,再统一注册,避免安装到一半留下部分全局组件。\n\t\tconst registrations = [main, ...extraEntries.map(([, component]) => component)].map((component) =>\n\t\t\tprepareComponentRegistration(app, component)\n\t\t);\n\t\tfor (const registration of registrations) {\n\t\t\tif (!registration.registered) app.component(registration.name, registration.component);\n\t\t}\n\t};\n\treturn installable;\n}\n\n/**\n * 为不需要单独注册的附属组件附加空安装函数。\n *\n * @remarks 适用于只能作为主组件附属属性使用、但仍需满足 Vue Plugin 类型的组件。\n * 函数直接修改并返回传入组件,不会向 Vue 3 App 注册内容。\n * @param component - 尚未定义或继承 `install` 属性的组件。\n * @returns 原组件引用及无副作用的 `install` 方法。\n * @throws `TypeError` 当组件自身或原型链已经存在 `install`。\n */\nexport function withNoopInstall<Value extends VueInstallValue>(component: Value): TSXWithInstall<Value> {\n\tif (\"install\" in Object(component)) throw new TypeError(\"The Vue component already defines an install property.\");\n\tconst installable = component as TSXWithInstall<Value>;\n\tinstallable.install = (): void => undefined;\n\treturn installable;\n}\n\n/**\n * 为 Vue 3 指令附加插件安装能力。\n *\n * @remarks 函数直接修改并返回指令。安装时重复注册同一引用保持幂等,不会覆盖同名的\n * 其他指令。名称只传给 `directive()`,不得包含 `v-` 前缀。\n * @param directive - 尚未定义或继承 `install` 属性的 Vue 指令对象。\n * @param name - 非空、无空白且不以 `v-` 开头的全局指令名。\n * @returns 原指令引用及 Vue Plugin `install` 方法。\n * @throws `TypeError` 当名称非法、指令已有 `install`,或安装目标无效。\n * @throws `Error` 当 App 中同名位置已经注册其他指令。\n */\nexport function withInstallDirective<Value extends VueInstallValue>(directive: Value, name: string): Installable<Value> {\n\tif (name.length === 0 || /\\s/u.test(name) || name.startsWith(\"v-\")) {\n\t\tthrow new TypeError(\"Installable Vue directives require a name without whitespace or a v- prefix.\");\n\t}\n\tif (\"install\" in Object(directive)) throw new TypeError(\"The Vue directive already defines an install property.\");\n\tconst installable = directive as Installable<Value>;\n\tinstallable.install = (value: App): void => {\n\t\tconst app = assertApp(value);\n\t\tconst existing = app.directive(name);\n\t\tif (existing !== undefined && existing !== directive) {\n\t\t\tthrow new Error(`Vue directive name \"${name}\" is already registered by another directive.`);\n\t\t}\n\t\tif (existing !== directive) app.directive(name, directive);\n\t};\n\treturn installable;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComputedRef, PropType } from "vue";
|
|
2
|
+
//#region src/vue/props.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* 为 Vue 运行时 Props 构造器附加泛型类型。
|
|
5
|
+
*
|
|
6
|
+
* @remarks 该函数只帮助 TypeScript 建模,不验证运行时值与 `Value` 一致;调用方仍应
|
|
7
|
+
* 传入 Vue 支持的构造器或构造器数组。
|
|
8
|
+
* @param runtimeType - Vue 支持的运行时构造器或构造器数组。
|
|
9
|
+
* @returns 同一引用,仅在类型层收窄为 `PropType<Value>`。
|
|
10
|
+
*/
|
|
11
|
+
declare function definePropType<Value>(runtimeType: unknown): PropType<Value>;
|
|
12
|
+
/**
|
|
13
|
+
* 构建需要透传给子组件的响应式 Props。
|
|
14
|
+
*
|
|
15
|
+
* @param props - Vue `setup` 接收的只读响应式 Props 对象。
|
|
16
|
+
* @param rawProps - 子组件的运行时 Props 配置。
|
|
17
|
+
* @param ignoredProps - 不需要透传的 Props 名称。
|
|
18
|
+
* @returns 只包含 `rawProps` 声明键且随 Props 更新的 ComputedRef。
|
|
19
|
+
*/
|
|
20
|
+
declare function useProps<Props extends object, RawProps extends object>(props: Props, rawProps: RawProps, ignoredProps?: readonly (keyof RawProps)[]): ComputedRef<Pick<Props, Extract<keyof Props, keyof RawProps>>>;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { definePropType, useProps };
|
|
23
|
+
//# sourceMappingURL=props.d.mts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { computed } from "vue";
|
|
2
|
+
//#region src/vue/props.ts
|
|
3
|
+
/**
|
|
4
|
+
* 为 Vue 运行时 Props 构造器附加泛型类型。
|
|
5
|
+
*
|
|
6
|
+
* @remarks 该函数只帮助 TypeScript 建模,不验证运行时值与 `Value` 一致;调用方仍应
|
|
7
|
+
* 传入 Vue 支持的构造器或构造器数组。
|
|
8
|
+
* @param runtimeType - Vue 支持的运行时构造器或构造器数组。
|
|
9
|
+
* @returns 同一引用,仅在类型层收窄为 `PropType<Value>`。
|
|
10
|
+
*/
|
|
11
|
+
function definePropType(runtimeType) {
|
|
12
|
+
return runtimeType;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 构建需要透传给子组件的响应式 Props。
|
|
16
|
+
*
|
|
17
|
+
* @param props - Vue `setup` 接收的只读响应式 Props 对象。
|
|
18
|
+
* @param rawProps - 子组件的运行时 Props 配置。
|
|
19
|
+
* @param ignoredProps - 不需要透传的 Props 名称。
|
|
20
|
+
* @returns 只包含 `rawProps` 声明键且随 Props 更新的 ComputedRef。
|
|
21
|
+
*/
|
|
22
|
+
function useProps(props, rawProps, ignoredProps = []) {
|
|
23
|
+
const ignored = new Set(ignoredProps);
|
|
24
|
+
return computed(() => {
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const key of Reflect.ownKeys(rawProps)) {
|
|
27
|
+
if (ignored.has(key) || !Object.hasOwn(props, key)) continue;
|
|
28
|
+
Object.defineProperty(result, key, {
|
|
29
|
+
configurable: true,
|
|
30
|
+
enumerable: true,
|
|
31
|
+
value: Reflect.get(props, key),
|
|
32
|
+
writable: true
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { definePropType, useProps };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=props.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"props.mjs","names":[],"sources":["../../src/vue/props.ts"],"sourcesContent":["import { computed } from \"vue\";\nimport type { ComputedRef, PropType } from \"vue\";\n\n/**\n * 为 Vue 运行时 Props 构造器附加泛型类型。\n *\n * @remarks 该函数只帮助 TypeScript 建模,不验证运行时值与 `Value` 一致;调用方仍应\n * 传入 Vue 支持的构造器或构造器数组。\n * @param runtimeType - Vue 支持的运行时构造器或构造器数组。\n * @returns 同一引用,仅在类型层收窄为 `PropType<Value>`。\n */\nexport function definePropType<Value>(runtimeType: unknown): PropType<Value> {\n\treturn runtimeType as PropType<Value>;\n}\n\n/**\n * 构建需要透传给子组件的响应式 Props。\n *\n * @param props - Vue `setup` 接收的只读响应式 Props 对象。\n * @param rawProps - 子组件的运行时 Props 配置。\n * @param ignoredProps - 不需要透传的 Props 名称。\n * @returns 只包含 `rawProps` 声明键且随 Props 更新的 ComputedRef。\n */\nexport function useProps<Props extends object, RawProps extends object>(\n\tprops: Props,\n\trawProps: RawProps,\n\tignoredProps: readonly (keyof RawProps)[] = []\n): ComputedRef<Pick<Props, Extract<keyof Props, keyof RawProps>>> {\n\tconst ignored = new Set<PropertyKey>(ignoredProps);\n\treturn computed<Pick<Props, Extract<keyof Props, keyof RawProps>>>(() => {\n\t\tconst result = {} as Pick<Props, Extract<keyof Props, keyof RawProps>>;\n\t\tfor (const key of Reflect.ownKeys(rawProps)) {\n\t\t\tif (ignored.has(key) || !Object.hasOwn(props, key)) continue;\n\t\t\tObject.defineProperty(result, key, { configurable: true, enumerable: true, value: Reflect.get(props, key), writable: true });\n\t\t}\n\t\treturn result;\n\t});\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,eAAsB,aAAuC;CAC5E,OAAO;AACR;;;;;;;;;AAUA,SAAgB,SACf,OACA,UACA,eAA4C,CAAC,GACoB;CACjE,MAAM,UAAU,IAAI,IAAiB,YAAY;CACjD,OAAO,eAAkE;EACxE,MAAM,SAAS,CAAC;EAChB,KAAK,MAAM,OAAO,QAAQ,QAAQ,QAAQ,GAAG;GAC5C,IAAI,QAAQ,IAAI,GAAG,KAAK,CAAC,OAAO,OAAO,OAAO,GAAG,GAAG;GACpD,OAAO,eAAe,QAAQ,KAAK;IAAE,cAAc;IAAM,YAAY;IAAM,OAAO,QAAQ,IAAI,OAAO,GAAG;IAAG,UAAU;GAAK,CAAC;EAC5H;EACA,OAAO;CACR,CAAC;AACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { VNode } from "vue";
|
|
2
|
+
//#region src/vue/render.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* 在当前 Vue 3 组件实例上安装 TSX 渲染函数。
|
|
5
|
+
* @remarks `setup` 仍可返回状态对象,因此状态能够显示在 Vue Devtools 中。
|
|
6
|
+
* @param render - 当前组件的渲染函数。
|
|
7
|
+
* @throws 不在组件 `setup` 调用栈中使用时抛出 `Error`。
|
|
8
|
+
*/
|
|
9
|
+
declare function useRender(render: () => VNode): void;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { useRender };
|
|
12
|
+
//# sourceMappingURL=render.d.mts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getCurrentInstance } from "vue";
|
|
2
|
+
//#region src/vue/render.ts
|
|
3
|
+
/**
|
|
4
|
+
* 在当前 Vue 3 组件实例上安装 TSX 渲染函数。
|
|
5
|
+
* @remarks `setup` 仍可返回状态对象,因此状态能够显示在 Vue Devtools 中。
|
|
6
|
+
* @param render - 当前组件的渲染函数。
|
|
7
|
+
* @throws 不在组件 `setup` 调用栈中使用时抛出 `Error`。
|
|
8
|
+
*/
|
|
9
|
+
function useRender(render) {
|
|
10
|
+
const instance = getCurrentInstance();
|
|
11
|
+
if (instance === null) throw new Error("useRender must be called from inside a setup function.");
|
|
12
|
+
instance.render = render;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { useRender };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=render.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.mjs","names":[],"sources":["../../src/vue/render.ts"],"sourcesContent":["import { getCurrentInstance } from \"vue\";\nimport type { VNode } from \"vue\";\n\n/** `useRender` 需要写入的 Vue 3 内部组件实例字段。 */\ninterface MutableVueComponentInstance {\n\trender?: () => VNode;\n}\n\n/**\n * 在当前 Vue 3 组件实例上安装 TSX 渲染函数。\n * @remarks `setup` 仍可返回状态对象,因此状态能够显示在 Vue Devtools 中。\n * @param render - 当前组件的渲染函数。\n * @throws 不在组件 `setup` 调用栈中使用时抛出 `Error`。\n */\nexport function useRender(render: () => VNode): void {\n\tconst instance = getCurrentInstance();\n\tif (instance === null) throw new Error(\"useRender must be called from inside a setup function.\");\n\t(instance as unknown as MutableVueComponentInstance).render = render;\n}\n"],"mappings":";;;;;;;;AAcA,SAAgB,UAAU,QAA2B;CACpD,MAAM,WAAW,mBAAmB;CACpC,IAAI,aAAa,MAAM,MAAM,IAAI,MAAM,wDAAwD;CAC/F,SAAqD,SAAS;AAC/D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SlotsType, VNode } from "vue";
|
|
2
|
+
//#region src/vue/slots.d.ts
|
|
3
|
+
/** Slot 名到 Props 类型的内部声明映射。 */
|
|
4
|
+
type RawSlots = Record<string, unknown>;
|
|
5
|
+
/** 根据 Slot Props 是否为 never 生成无参数或有参数的 Slot 签名。 */
|
|
6
|
+
type VueSlot<Properties> = [Properties] extends [never] ? () => VNode[] : (properties: Properties) => VNode[];
|
|
7
|
+
/** 把 Slot 名称与作用域参数映射为 Vue 3 Slot 函数。 */
|
|
8
|
+
type TypedSlots<Slots extends RawSlots> = { [Name in keyof Slots]: VueSlot<Slots[Name]>; };
|
|
9
|
+
/** Vue 3 `slots` 选项接受的运行时声明与官方静态类型标记。 */
|
|
10
|
+
type TypedSlotsDeclaration<Slots extends RawSlots> = SlotsType<Partial<TypedSlots<Slots>>>;
|
|
11
|
+
/**
|
|
12
|
+
* 为 Options API 的 `slots` 选项创建带作用域参数的类型声明。
|
|
13
|
+
*
|
|
14
|
+
* @returns 运行时 `Object` 构造器,并携带仅供 TypeScript 使用的 Slot 类型标记。
|
|
15
|
+
*/
|
|
16
|
+
declare function makeSlots<Slots extends RawSlots>(): TypedSlotsDeclaration<Slots>;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { TypedSlots, TypedSlotsDeclaration, makeSlots };
|
|
19
|
+
//# sourceMappingURL=slots.d.mts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/vue/slots.ts
|
|
2
|
+
/**
|
|
3
|
+
* 为 Options API 的 `slots` 选项创建带作用域参数的类型声明。
|
|
4
|
+
*
|
|
5
|
+
* @returns 运行时 `Object` 构造器,并携带仅供 TypeScript 使用的 Slot 类型标记。
|
|
6
|
+
*/
|
|
7
|
+
function makeSlots() {
|
|
8
|
+
return Object;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { makeSlots };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=slots.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.mjs","names":[],"sources":["../../src/vue/slots.ts"],"sourcesContent":["import type { SlotsType, VNode } from \"vue\";\n\n/** Slot 名到 Props 类型的内部声明映射。 */\ntype RawSlots = Record<string, unknown>;\n/** 根据 Slot Props 是否为 never 生成无参数或有参数的 Slot 签名。 */\ntype VueSlot<Properties> = [Properties] extends [never] ? () => VNode[] : (properties: Properties) => VNode[];\n\n/** 把 Slot 名称与作用域参数映射为 Vue 3 Slot 函数。 */\nexport type TypedSlots<Slots extends RawSlots> = {\n\t[Name in keyof Slots]: VueSlot<Slots[Name]>;\n};\n\n/** Vue 3 `slots` 选项接受的运行时声明与官方静态类型标记。 */\nexport type TypedSlotsDeclaration<Slots extends RawSlots> = SlotsType<Partial<TypedSlots<Slots>>>;\n\n/**\n * 为 Options API 的 `slots` 选项创建带作用域参数的类型声明。\n *\n * @returns 运行时 `Object` 构造器,并携带仅供 TypeScript 使用的 Slot 类型标记。\n */\nexport function makeSlots<Slots extends RawSlots>(): TypedSlotsDeclaration<Slots> {\n\treturn Object as TypedSlotsDeclaration<Slots>;\n}\n"],"mappings":";;;;;;AAoBA,SAAgB,YAAkE;CACjF,OAAO;AACR"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/vue/with.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* 保留传入值并显式指定其 TypeScript 类型。
|
|
4
|
+
*
|
|
5
|
+
* @remarks 未传值时运行时结果为 `undefined`,仅适合为 reactive 对象的初始字段提供类型。
|
|
6
|
+
* @param data - 可选的原始值。
|
|
7
|
+
* @returns 传入值本身;省略时返回类型化的 `undefined`。
|
|
8
|
+
*/
|
|
9
|
+
declare function withDefineType<Value>(data?: Value): Value;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { withDefineType };
|
|
12
|
+
//# sourceMappingURL=with.d.mts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/vue/with.ts
|
|
2
|
+
/**
|
|
3
|
+
* 保留传入值并显式指定其 TypeScript 类型。
|
|
4
|
+
*
|
|
5
|
+
* @remarks 未传值时运行时结果为 `undefined`,仅适合为 reactive 对象的初始字段提供类型。
|
|
6
|
+
* @param data - 可选的原始值。
|
|
7
|
+
* @returns 传入值本身;省略时返回类型化的 `undefined`。
|
|
8
|
+
*/
|
|
9
|
+
function withDefineType(data) {
|
|
10
|
+
return data;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { withDefineType };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=with.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with.mjs","names":[],"sources":["../../src/vue/with.ts"],"sourcesContent":["/**\n * 保留传入值并显式指定其 TypeScript 类型。\n *\n * @remarks 未传值时运行时结果为 `undefined`,仅适合为 reactive 对象的初始字段提供类型。\n * @param data - 可选的原始值。\n * @returns 传入值本身;省略时返回类型化的 `undefined`。\n */\nexport function withDefineType<Value>(data?: Value): Value {\n\treturn data as Value;\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,eAAsB,MAAqB;CAC1D,OAAO;AACR"}
|
package/docs/API.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Fast.Utils API
|
|
2
|
+
|
|
3
|
+
Fast.Utils is a browser-first utility package targeting ES2022. Package managers use its ESM entry, while CDNs use the separately minified IIFE entry. Its application environments are modern browsers, WebViews, Vue 3, and uni-app.
|
|
4
|
+
|
|
5
|
+
## Imports
|
|
6
|
+
|
|
7
|
+
The package has one public root entry. Every utility, including the Vue helpers, is exposed as a named export.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { chunk, configureStorage, installationIdentity, Local } from "@fast-china/utils";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Internal helpers are not public subpaths. Aggregate utility objects are not exported; import named functions so bundlers can remove unused code.
|
|
14
|
+
|
|
15
|
+
## Storage
|
|
16
|
+
|
|
17
|
+
`Local` and `Session` initialize lazily with the legacy-compatible `fast__` prefix, JSON codec, and `Date.now`. Calling `configureStorage` is optional unless the defaults must be overridden.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { Local, Session } from "@fast-china/utils";
|
|
21
|
+
|
|
22
|
+
Local.set("profile", { name: "Ada" }, { ttlMs: 3_600_000 });
|
|
23
|
+
Session.set("draft", { step: 2 });
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`Local` and `Session` provide `get`, `set`, `has`, `remove`, `removeByPrefix`, `keys`, `pruneExpired`, and namespace-scoped `clear`. Missing and expired values return `undefined`. Invalid TTL values, empty prefixes, malformed stored envelopes, unavailable platform storage, and conflicting repeated configuration throw errors. Native storage quota and privacy errors are propagated. Custom options must be configured before the first Storage operation.
|
|
27
|
+
|
|
28
|
+
For uni-app, the first Storage operation or an explicit `configureStorage` call detects the global `uni` object and uses its synchronous Storage API. uni-app has no separate session backend, so `Session` throws when called in this mode.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { Local } from "@fast-china/utils";
|
|
32
|
+
|
|
33
|
+
Local.set("token", "value");
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`configureStorage({ prefix: "admin:", crypto: true })` restores the old global prefix and Base64-obfuscation options. `crypto: true` and `base64StorageCodec` are reversible encoding rather than encryption and must not protect secrets. A custom `codec` may be supplied instead of `crypto`.
|
|
37
|
+
|
|
38
|
+
`encodeSecureBase64` and `decodeSecureBase64` preserve the legacy dictionary payload while using a Web Crypto random prefix. Given the same default six-character prefix, valid legacy payloads remain byte-for-byte compatible. The old dictionary references an unavailable character for Base64 lengths 101–124, so the current implementation inserts a one-character fallback that the legacy removal flow can decode. The old custom-length argument always generated six random characters; the current API correctly generates `prefixLength` characters. Custom lengths must match during encoding and decoding; `0` disables both the prefix and dictionary insertion. The format remains reversible encoding rather than encryption.
|
|
39
|
+
|
|
40
|
+
## Identity
|
|
41
|
+
|
|
42
|
+
`installationIdentity` is the global installation identifier facade. Call `configureInstallationIdentity` in the application entry before first use to override its `identity:installation-id` cache key. `getOrCreateInstallationId(installationId?)` loads, creates, or replaces its UUID v4 value in `Local` storage. Storage uses its defaults when no explicit configuration was supplied. UUID generation requires Web Crypto and never falls back to `Math.random()`.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { configureInstallationIdentity, configureStorage, getOrCreateInstallationId, installationIdentity } from "@fast-china/utils";
|
|
46
|
+
|
|
47
|
+
configureStorage({ prefix: "app:" });
|
|
48
|
+
configureInstallationIdentity({ cacheKey: "account:installation-id" });
|
|
49
|
+
getOrCreateInstallationId();
|
|
50
|
+
installationIdentity.read();
|
|
51
|
+
installationIdentity.clear();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The identifier is an installation-scoped value, not a hardware identifier, authentication credential, secret, or anti-fraud signal.
|
|
55
|
+
|
|
56
|
+
## Logger
|
|
57
|
+
|
|
58
|
+
Logger scope belongs to each message rather than a mutable logger or child instance:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { logger } from "@fast-china/utils";
|
|
62
|
+
|
|
63
|
+
logger.info("storage", "profile loaded", { userId: 1 });
|
|
64
|
+
logger.error("network", "request failed", error);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`createLogger` configures the minimum level, brand prefix, sink, and optional uni-app App-Plus split output. Scope must be a non-empty string without surrounding whitespace.
|
|
68
|
+
|
|
69
|
+
## Crypto
|
|
70
|
+
|
|
71
|
+
The TypeScript Crypto public API mirrors the public methods and algorithm casing of .NET `CryptoUtil`:
|
|
72
|
+
|
|
73
|
+
| Capability | Shared method names |
|
|
74
|
+
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
75
|
+
| Secure random and byte comparison | `GenerateRandomBytes`, `FixedTimeEquals` |
|
|
76
|
+
| MD5, SHA-1, and SHA-2 digests | `MD5Encrypt`, `SHA1Encrypt`, `SHA256Encrypt`, `SHA256Bytes`, `SHA384Encrypt`, `SHA384Bytes`, `SHA512Encrypt`, `SHA512Bytes` |
|
|
77
|
+
| HMAC | `HMACSHA256Encrypt`, `HMACSHA384Encrypt`, `HMACSHA512Encrypt` |
|
|
78
|
+
| Password derivation and hashing | `PBKDF2SHA256`, `HashPasswordPBKDF2SHA256`, `VerifyPasswordPBKDF2SHA256` |
|
|
79
|
+
| HKDF | `HKDFSHA256` |
|
|
80
|
+
| AES | `AESEncrypt`, `AESDecrypt`, `AESEncryptAuthenticated`, `AESDecryptAuthenticated`, `AESEncryptWithPassword`, `AESDecryptWithPassword` |
|
|
81
|
+
| RSA | `GenerateRSAKeyPair`, `RSAEncryptOAEP`, `RSADecryptOAEP`, `RSASignPSS`, `RSAVerifyPSS` |
|
|
82
|
+
| Elliptic curves | `GenerateECDSAKeyPair`, `ECDSASign`, `ECDSAVerify`, `GenerateECDHKeyPair`, `DeriveECDHSecret`, `DeriveECDHKeySHA256` |
|
|
83
|
+
|
|
84
|
+
The Base64 v1 payload produced by `AESEncryptAuthenticated`, the `FAST-AES-256-GCM-V2` password payload, PBKDF2 password hashes, and PKCS#8/SPKI PEM keys interoperate with .NET in both directions. MD5 and HMAC output lowercase hexadecimal; SHA-1/256/384/512 output uppercase hexadecimal, matching .NET.
|
|
85
|
+
|
|
86
|
+
Store passwords with `HashPasswordPBKDF2SHA256` and `VerifyPasswordPBKDF2SHA256`; the result is not decryptable. AES-GCM provides confidentiality and integrity, HMAC authenticates with a shared key, SHA-2 computes digests, and HKDF/PBKDF2 derive keys. MD5, SHA-1, AES-CBC, and AES-ECB do not provide modern password-storage or authenticated-encryption guarantees.
|
|
87
|
+
|
|
88
|
+
## Modules
|
|
89
|
+
|
|
90
|
+
- `array`: `chunk`, `removeNullishValues`, `unique`, `uniqueBy`, `groupBy`, `partition`, `difference`, `intersection`, `hasDuplicatesBy`, and `allEqualBy`.
|
|
91
|
+
- `async`: abort-aware `sleep`, timeout, retry, bounded concurrent mapping, debounce, and throttle primitives.
|
|
92
|
+
- `base64`: strict UTF-8 Base64/Base64URL byte and text functions plus the historical Latin-1 and dictionary-obfuscation functions.
|
|
93
|
+
- `color`: Hex parsing/formatting/mixing, explicit black/white mixing, luminance, and contrast helpers.
|
|
94
|
+
- `crypto`: secure randomness, digests, HMAC, PBKDF2, HKDF, AES, RSA-OAEP/PSS, ECDSA, and ECDH.
|
|
95
|
+
- `date`: date validation and arithmetic, day ranges, relative formatting, and the seven historical date helpers as named functions.
|
|
96
|
+
- `dom`: CSS unit and style serialization helpers.
|
|
97
|
+
- `env`: capability and user-agent detection. Detection does not expand the supported runtime contract.
|
|
98
|
+
- `logger`: isolated configurable loggers and the default `logger`.
|
|
99
|
+
- `number`: ranges, rounding, aggregation, interpolation, byte formatting, and secure integer generation.
|
|
100
|
+
- `object`: prototype-safe selection, comparison, mapping, and query serialization. Style serialization is provided by the `dom` module.
|
|
101
|
+
- `string`: query parsing, casing, grapheme-aware truncation, UUID, secure random strings, escaping, and whitespace normalization.
|
|
102
|
+
- `vue`: Composition API, type, render, and `app.use()` registration helpers for Vue 3.
|
|
103
|
+
|
|
104
|
+
## Security and limits
|
|
105
|
+
|
|
106
|
+
AES-GCM provides confidentiality and integrity; AES-CBC/ECB do not authenticate ciphertexts. MD5, SHA-1, and the historical Base64 dictionary must not protect passwords, signatures, or sensitive data. Cryptographic helpers enforce algorithm-specific parameter and payload limits and require Web Crypto where applicable.
|
|
107
|
+
|
|
108
|
+
Query and object helpers reject prototype-polluting keys. URL decoders are bounded. Storage cleanup is always restricted to the configured namespace. Browser globals are resolved only when an API is called, never during module import.
|
|
109
|
+
|
|
110
|
+
## Errors and compatibility
|
|
111
|
+
|
|
112
|
+
Programming errors, invalid inputs, unsupported platform capabilities, and malformed protected data throw native errors unless a function explicitly documents a nullable result.
|