@anjianshi/utils 2.9.0 → 3.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.
Files changed (164) hide show
  1. package/README.md +10 -0
  2. package/eslint.config.cjs +33 -0
  3. package/package.json +19 -10
  4. package/publish-prepare.cjs +16 -0
  5. package/src/env-browser/device.ts +62 -0
  6. package/src/env-browser/global.ts +21 -0
  7. package/src/env-browser/load-script.ts +13 -0
  8. package/src/env-browser/logging.ts +58 -0
  9. package/src/env-browser/manage-vconsole.ts +54 -0
  10. package/src/env-node/crypto-random.ts +30 -0
  11. package/src/env-node/fs.ts +50 -0
  12. package/src/env-node/index.ts +5 -0
  13. package/src/env-node/logging/handlers.ts +190 -0
  14. package/src/env-node/logging/index.ts +16 -0
  15. package/{env-react/emotion-register-globals.d.ts → src/env-react/emotion-register-globals.ts} +5 -2
  16. package/src/env-react/emotion.tsx +42 -0
  17. package/src/env-react/hooks.ts +59 -0
  18. package/src/env-react/index.ts +1 -0
  19. package/src/env-react/react-register-globals.ts +53 -0
  20. package/src/env-service/controllers.ts +93 -0
  21. package/src/env-service/env-reader.ts +141 -0
  22. package/src/env-service/index.ts +6 -0
  23. package/src/env-service/prisma/adapt-logging.ts +39 -0
  24. package/src/env-service/prisma/extensions/exist.ts +21 -0
  25. package/src/env-service/prisma/extensions/find-and-count.ts +24 -0
  26. package/src/env-service/prisma/extensions/soft-delete.ts +162 -0
  27. package/src/env-service/prisma/extensions/with-transaction.ts +65 -0
  28. package/src/env-service/prisma/index.ts +6 -0
  29. package/src/env-service/prisma/transaction-contexted.ts +80 -0
  30. package/src/env-service/redis-cache.ts +142 -0
  31. package/src/env-service/tasks.ts +45 -0
  32. package/src/index.ts +4 -0
  33. package/src/init-dayjs.ts +8 -0
  34. package/src/lang/async.ts +47 -0
  35. package/src/lang/color.ts +119 -0
  36. package/src/lang/index.ts +8 -0
  37. package/src/lang/object.ts +39 -0
  38. package/src/lang/random.ts +25 -0
  39. package/src/lang/result.ts +78 -0
  40. package/src/lang/string.ts +95 -0
  41. package/src/lang/time.ts +19 -0
  42. package/{lang/types.d.ts → src/lang/types.ts} +43 -23
  43. package/src/logging/adapt.ts +49 -0
  44. package/src/logging/formatters.ts +23 -0
  45. package/src/logging/index.ts +106 -0
  46. package/src/md5.ts +318 -0
  47. package/src/safe-request.ts +193 -0
  48. package/src/url.ts +185 -0
  49. package/src/validators/array.ts +97 -0
  50. package/src/validators/base.ts +145 -0
  51. package/src/validators/boolean.ts +21 -0
  52. package/src/validators/datetime.ts +39 -0
  53. package/src/validators/factory.ts +244 -0
  54. package/src/validators/index.ts +9 -0
  55. package/src/validators/number.ts +54 -0
  56. package/src/validators/object.ts +101 -0
  57. package/src/validators/one-of.ts +33 -0
  58. package/src/validators/string.ts +72 -0
  59. package/env-browser/device.d.ts +0 -24
  60. package/env-browser/device.js +0 -50
  61. package/env-browser/global.d.ts +0 -10
  62. package/env-browser/global.js +0 -15
  63. package/env-browser/load-script.d.ts +0 -5
  64. package/env-browser/load-script.js +0 -13
  65. package/env-browser/logging.d.ts +0 -18
  66. package/env-browser/logging.js +0 -49
  67. package/env-browser/manage-vconsole.d.ts +0 -16
  68. package/env-browser/manage-vconsole.js +0 -38
  69. package/env-node/crypto-random.d.ts +0 -13
  70. package/env-node/crypto-random.js +0 -28
  71. package/env-node/fs.d.ts +0 -19
  72. package/env-node/fs.js +0 -48
  73. package/env-node/index.d.ts +0 -6
  74. package/env-node/index.js +0 -6
  75. package/env-node/logging/handlers.d.ts +0 -58
  76. package/env-node/logging/handlers.js +0 -154
  77. package/env-node/logging/index.d.ts +0 -11
  78. package/env-node/logging/index.js +0 -14
  79. package/env-node/safe-request.d.ts +0 -26
  80. package/env-node/safe-request.js +0 -40
  81. package/env-react/emotion-register-globals.js +0 -5
  82. package/env-react/emotion.d.ts +0 -20
  83. package/env-react/emotion.jsx +0 -34
  84. package/env-react/hooks.d.ts +0 -4
  85. package/env-react/hooks.js +0 -16
  86. package/env-react/index.d.ts +0 -1
  87. package/env-react/index.js +0 -1
  88. package/env-react/react-register-globals.d.ts +0 -21
  89. package/env-react/react-register-globals.js +0 -19
  90. package/env-service/controllers.d.ts +0 -30
  91. package/env-service/controllers.js +0 -41
  92. package/env-service/env-reader.d.ts +0 -55
  93. package/env-service/env-reader.js +0 -79
  94. package/env-service/index.d.ts +0 -6
  95. package/env-service/index.js +0 -6
  96. package/env-service/prisma/adapt-logging.d.ts +0 -21
  97. package/env-service/prisma/adapt-logging.js +0 -30
  98. package/env-service/prisma/extensions/exist.d.ts +0 -10
  99. package/env-service/prisma/extensions/exist.js +0 -16
  100. package/env-service/prisma/extensions/find-and-count.d.ts +0 -7
  101. package/env-service/prisma/extensions/find-and-count.js +0 -19
  102. package/env-service/prisma/extensions/soft-delete.d.ts +0 -52
  103. package/env-service/prisma/extensions/soft-delete.js +0 -123
  104. package/env-service/prisma/extensions/with-transaction.d.ts +0 -9
  105. package/env-service/prisma/extensions/with-transaction.js +0 -54
  106. package/env-service/prisma/index.d.ts +0 -6
  107. package/env-service/prisma/index.js +0 -6
  108. package/env-service/prisma/transaction-contexted.d.ts +0 -11
  109. package/env-service/prisma/transaction-contexted.js +0 -52
  110. package/env-service/redis-cache.d.ts +0 -39
  111. package/env-service/redis-cache.js +0 -116
  112. package/env-service/tasks.d.ts +0 -12
  113. package/env-service/tasks.js +0 -37
  114. package/index.d.ts +0 -3
  115. package/index.js +0 -3
  116. package/init-dayjs.d.ts +0 -2
  117. package/init-dayjs.js +0 -7
  118. package/lang/async.d.ts +0 -19
  119. package/lang/async.js +0 -34
  120. package/lang/color.d.ts +0 -37
  121. package/lang/color.js +0 -111
  122. package/lang/index.d.ts +0 -8
  123. package/lang/index.js +0 -8
  124. package/lang/may-success.d.ts +0 -40
  125. package/lang/may-success.js +0 -27
  126. package/lang/object.d.ts +0 -12
  127. package/lang/object.js +0 -41
  128. package/lang/random.d.ts +0 -13
  129. package/lang/random.js +0 -24
  130. package/lang/string.d.ts +0 -29
  131. package/lang/string.js +0 -92
  132. package/lang/time.d.ts +0 -10
  133. package/lang/time.js +0 -18
  134. package/lang/types.js +0 -28
  135. package/logging/adapt.d.ts +0 -10
  136. package/logging/adapt.js +0 -43
  137. package/logging/formatters.d.ts +0 -10
  138. package/logging/formatters.js +0 -22
  139. package/logging/index.d.ts +0 -45
  140. package/logging/index.js +0 -90
  141. package/md5.d.ts +0 -30
  142. package/md5.js +0 -308
  143. package/url.d.ts +0 -77
  144. package/url.js +0 -149
  145. package/validators/array.d.ts +0 -30
  146. package/validators/array.js +0 -47
  147. package/validators/base.d.ts +0 -82
  148. package/validators/base.js +0 -42
  149. package/validators/boolean.d.ts +0 -3
  150. package/validators/boolean.js +0 -22
  151. package/validators/datetime.d.ts +0 -12
  152. package/validators/datetime.js +0 -30
  153. package/validators/factory.d.ts +0 -70
  154. package/validators/factory.js +0 -121
  155. package/validators/index.d.ts +0 -9
  156. package/validators/index.js +0 -9
  157. package/validators/number.d.ts +0 -19
  158. package/validators/number.js +0 -26
  159. package/validators/object.d.ts +0 -28
  160. package/validators/object.js +0 -49
  161. package/validators/one-of.d.ts +0 -10
  162. package/validators/one-of.js +0 -15
  163. package/validators/string.d.ts +0 -22
  164. package/validators/string.js +0 -35
package/url.js DELETED
@@ -1,149 +0,0 @@
1
- /**
2
- * URL 工具函数
3
- * 部分灵感来自:https://www.npmjs.com/package/qs
4
- *
5
- * [名词定义]
6
- * query: 指 a=1&b=2 格式的“查询字符串”或此类字符串的解析结果。
7
- * search: URL 中的 search 部分,与 location.search 一致,空字符串或以 '?' 开头。
8
- * hash: URL 中的 hash 部分,与 location.hash 一直,空字符串或以 '#' 开头。
9
- */
10
- import isPlainObject from 'lodash/isPlainObject.js';
11
- function parseQuery(url, options) {
12
- const { array = false, loose = false, decode = true } = options ?? {};
13
- // 正常状态下,将仅剩 a=1&b=1(即不会再有 ? 和 #);loose 模式下,可能为 a=1&b=2#c=3?d=4
14
- const queryString = (loose ? /(\?|#)(.+)/ : /(\?)(.+?)(#|$)/).exec(url)?.[2] ?? '';
15
- if (!queryString)
16
- return {};
17
- const query = {};
18
- const reg = /([^#?&]*)=([^#?&]*)/g;
19
- let re = reg.exec(queryString);
20
- while (re) {
21
- const [name, rawValue] = [re[1], re[2]];
22
- const value = decode ? safeDecode(rawValue) : rawValue;
23
- if (array && query[name] !== undefined) {
24
- const prev = query[name];
25
- query[name] = Array.isArray(prev) ? [...prev, value] : [prev, value];
26
- }
27
- else {
28
- query[name] = value;
29
- }
30
- re = reg.exec(queryString);
31
- }
32
- return query;
33
- }
34
- export { parseQuery };
35
- export function stringifyQuery(obj, encode = true) {
36
- if (!isPlainObject(obj))
37
- return '';
38
- return (Object.entries(obj)
39
- // 过滤值为 undefined 的项目,使其完全不出现在最终的 query 中
40
- .filter((entry) => entry[1] !== undefined)
41
- .map(([name, value]) => stringifyQueryItem(name, value, encode))
42
- .join('&'));
43
- }
44
- function stringifyQueryItem(name, value, encode) {
45
- if (Array.isArray(value))
46
- return value.map(subValue => stringifyQueryItem(name, subValue, encode)).join('&');
47
- if (typeof value === 'boolean')
48
- value = value ? '1' : '0';
49
- if (typeof value === 'number')
50
- value = value.toString();
51
- if (encode)
52
- value = encodeURIComponent(value);
53
- return `${name}=${value}`;
54
- }
55
- /**
56
- * 拆分 URL 的各个部分
57
- *
58
- * bare 为 true,则 search 不带 '?',hash 不带 '#'
59
- * 否则和 location.search / hash 一样
60
- * (默认为 true)
61
- */
62
- export function splitUrl(url, bare = true) {
63
- let hashIndex = url.indexOf('#');
64
- if (hashIndex === -1)
65
- hashIndex = url.length;
66
- const bareHash = url.slice(hashIndex + 1);
67
- let searchIndex = url.slice(0, hashIndex).indexOf('?');
68
- if (searchIndex === -1)
69
- searchIndex = hashIndex;
70
- const bareSearch = url.slice(searchIndex + 1, hashIndex);
71
- return {
72
- base: url.slice(0, searchIndex),
73
- search: bare ? bareSearch : bareSearch ? '?' + bareSearch : '',
74
- hash: bare ? bareHash : bareHash ? '#' + bareHash : '',
75
- };
76
- }
77
- /**
78
- * 把 query 和 hash 内容合并到 url 上
79
- *
80
- * query object 与现有 search 合并,替换同名项(值为数组的,用新数组代替老的,不会合并数组)
81
- * hash string 带不带开头的 '#' 皆可。会代替 url 已有的 hash。
82
- */
83
- export function combineUrl(origUrl, query = {}, hash = '') {
84
- if (hash.startsWith('#'))
85
- hash = hash.slice(1);
86
- // 拆分原 url 的 search、hash
87
- const { base, search: origSearch, hash: origHash } = splitUrl(origUrl);
88
- // 拼接新 URL
89
- let newUrl = base;
90
- const newSearch = stringifyQuery({ ...parseQuery(origSearch), ...query });
91
- const newHash = hash || origHash;
92
- if (newSearch)
93
- newUrl += `?${newSearch}`;
94
- if (newHash)
95
- newUrl += `#${newHash}`;
96
- return newUrl;
97
- }
98
- /**
99
- * 移除路径中所有非必须的 "/"
100
- * 清理后的字符串只有这几种可能的格式:''、'abc'、'abc/def'
101
- * 例如 /abc/def 和 abc/def/ 都会变成 abc/def
102
- *
103
- * 注意:此操作不会统一大小写,因此不保证处理后两个字符串在代码层面全等(a === b)
104
- */
105
- export function clearSlash(path) {
106
- if (path.startsWith('/'))
107
- path = path.slice(1);
108
- if (path.endsWith('/'))
109
- path = path.slice(0, -1);
110
- path = path.replace(/\/+/g, '/');
111
- return path;
112
- }
113
- /**
114
- * 合并几段路径,保证合并处只有一个斜杠
115
- */
116
- export function joinPath(...nodes) {
117
- // - node 为 '' 时忽略 node
118
- // - path 可能的格式:'' 'a' 'a/' ‘/a/'
119
- // - path 为 '',则 node 开头 '/' 保持原样
120
- // - 否则,根据 path 结尾有没有 '/',决定 node 开头带不带 '/'
121
- // - node 开头、结尾若有多个 '/' 均替换成单个
122
- return nodes.reduce((path, node) => {
123
- if (!node)
124
- return path;
125
- const [, origPrefix, content, origSuffix] = /^(\/*)(.*?)(\/*)$/.exec(node);
126
- const prefix = (path === '' ? !!origPrefix : !path.endsWith('/')) ? '/' : '';
127
- const suffix = origSuffix ? '/' : '';
128
- const result = `${path}${prefix}${content}${suffix}`;
129
- return result;
130
- }, '');
131
- }
132
- /**
133
- * decodeURIComponent() 对于不规范编码的字符串可能会报错(例如字符串里出现了“%”)
134
- * 用此函数代替可避免此问题
135
- */
136
- export function safeDecode(content) {
137
- try {
138
- return decodeURIComponent(content);
139
- }
140
- catch (e) {
141
- return content;
142
- }
143
- }
144
- /**
145
- * 将 URL 中的 http:// 协议改成 https://
146
- */
147
- export function ensureHttps(url) {
148
- return url?.replace(/http:\/\//g, 'https://');
149
- }
@@ -1,30 +0,0 @@
1
- import { type CommonOptions, type Validator, type Validated } from './base.js';
2
- /** 验证元素数量任意、元素类型相同的数组 */
3
- export interface ArrayOptions extends CommonOptions {
4
- /** 验证数组各元素 */
5
- item: Validator<unknown, CommonOptions>;
6
- /** 数组最小长度 */
7
- min?: number;
8
- /** 数组最大长度 */
9
- max?: number;
10
- /** 是否对数组元素进行去重 @defaults false */
11
- unique?: boolean;
12
- /** 如果传入的不是数组,是否要将其视为数组内元素,包裹成数组 */
13
- toArray?: boolean;
14
- }
15
- type ArrayValues<Options extends ArrayOptions> = Validated<Options extends {
16
- item: Validator<infer T, CommonOptions>;
17
- } ? T : never, Options extends {
18
- item: Validator<unknown, infer T>;
19
- } ? T : never>[];
20
- export declare function getArrayValidator<Options extends ArrayOptions>(options: Options): Validator<ArrayValues<Options>, Options>;
21
- /** 验证元素数量固定、类型可以不同的数组 */
22
- export interface TupleOptions extends CommonOptions {
23
- /** 验证数组各元素(validator 与元素一一对应) */
24
- tuple: Validator<unknown, CommonOptions>[];
25
- }
26
- type TupleValues<Options extends TupleOptions> = {
27
- [Key in keyof Options['tuple']]: Options['tuple'][Key] extends Validator<infer Value, infer Options> ? Validated<Value, Options> : never;
28
- };
29
- export declare function getTupleValidator<const Options extends TupleOptions>(options: Options): Validator<TupleValues<Options>, Options>;
30
- export {};
@@ -1,47 +0,0 @@
1
- import { success, failed } from '../lang/index.js';
2
- import { getValidatorGenerator, } from './base.js';
3
- export function getArrayValidator(options) {
4
- return getValidatorGenerator(function validate(field, value, options) {
5
- if (!Array.isArray(value)) {
6
- if (options.toArray)
7
- value = [value];
8
- else
9
- return failed(`${field} should be an array`);
10
- }
11
- let formatted = [];
12
- if (typeof options.min === 'number' && value.length < options.min)
13
- return failed(`array ${field}'s length should >= ${options.min}`);
14
- if (typeof options.max === 'number' && value.length > options.max)
15
- return failed(`array ${field}'s length should <= ${options.max}`);
16
- const itemValidator = options.item;
17
- for (let i = 0; i < value.length; i++) {
18
- const itemResult = itemValidator(`${field}[${i}]`, value[i]);
19
- if (itemResult.success)
20
- formatted.push(itemResult.data);
21
- else
22
- return itemResult;
23
- }
24
- if (options.unique === true)
25
- formatted = [...new Set(formatted)];
26
- return success(formatted);
27
- })(options);
28
- }
29
- export function getTupleValidator(options) {
30
- return getValidatorGenerator(function validate(field, value, options) {
31
- if (!Array.isArray(value))
32
- return failed(`${field} should be an array`);
33
- if (value.length > options.tuple.length)
34
- return failed(`${field} should be a tuple with ${options.tuple.length} items`);
35
- const formatted = [];
36
- // 这种情况不能遍历 value,因为它的长度可能小于 opt.tuple
37
- for (let i = 0; i < options.tuple.length; i++) {
38
- const itemValidator = options.tuple[i];
39
- const itemResult = itemValidator(`${field}[${i}]`, value[i]);
40
- if (itemResult.success)
41
- formatted.push(itemResult.data);
42
- else
43
- return itemResult;
44
- }
45
- return success(formatted);
46
- })(options);
47
- }
@@ -1,82 +0,0 @@
1
- import { type MaySuccess } from '../lang/index.js';
2
- /**
3
- * 支持传入进行验证的值类型
4
- */
5
- export type AllowedInputValue = PrimitiveType | null | undefined;
6
- /**
7
- * JavaScript 基础值类型
8
- */
9
- export type PrimitiveType = string | boolean | number | PrimitiveType[] | [...PrimitiveType[]] | {
10
- [key: string]: PrimitiveType;
11
- };
12
- /**
13
- * validator 通用参数
14
- */
15
- export interface CommonOptions<Value = any> {
16
- /** 是否允许 null 值 @default false */
17
- null?: boolean;
18
- /** 字段是否必须有值(不能是 undefined) @default true */
19
- required?: boolean;
20
- /**
21
- * 默认值,字段无值(或值为 undefined)时生效,值为 null 不会生效。
22
- * 指定后 required 选项将失去作用。
23
- */
24
- defaults?: Value;
25
- custom?: (input: Value) => MaySuccess<Value>;
26
- [key: string]: unknown;
27
- }
28
- /**
29
- * 补全了的 Options
30
- */
31
- type FullfiledOptions<Options extends Partial<CommonOptions>> = Omit<Options, keyof CommonOptions> & {
32
- null: Options['null'] extends true ? true : false;
33
- required: Options['required'] extends false ? false : true;
34
- defaults: Options extends {
35
- defaults: infer T;
36
- } ? T : undefined;
37
- custom: Options extends {
38
- custom: infer T;
39
- } ? T : undefined;
40
- };
41
- /**
42
- * 验证完成后能得到的值类型
43
- */
44
- export type Validated<Value, InputOptions extends CommonOptions> = FullfiledOptions<InputOptions> extends {
45
- defaults: undefined;
46
- } ? FullfiledOptions<InputOptions> extends {
47
- required: false;
48
- null: false;
49
- } ? Value | undefined : FullfiledOptions<InputOptions> extends {
50
- required: false;
51
- null: true;
52
- } ? Value | undefined | null : FullfiledOptions<InputOptions> extends {
53
- required: true;
54
- null: false;
55
- } ? Value : FullfiledOptions<InputOptions> extends {
56
- required: true;
57
- null: true;
58
- } ? Value | null : Value : FullfiledOptions<InputOptions> extends {
59
- defaults: infer T;
60
- null: false;
61
- } ? Value | T : FullfiledOptions<InputOptions> extends {
62
- defaults: infer T;
63
- null: true;
64
- } ? Value | T | null : never;
65
- /**
66
- * 最终生成的 validator 函数类型
67
- */
68
- export interface Validator<Value, InputOptions extends CommonOptions> {
69
- (input: AllowedInputValue): MaySuccess<Validated<Value, InputOptions>>;
70
- (field: string, input: AllowedInputValue): MaySuccess<Validated<Value, InputOptions>>;
71
- }
72
- /**
73
- * 返回支持指定格式的 options、并按照传入的逻辑进行验证的 validator 的生成器。
74
- * 对 CommonOptions 相关内容的验证以自动包含在里面,只需要传入额外的验证逻辑即可。
75
- */
76
- export declare function getValidatorGenerator<Value, Options extends CommonOptions>(validate: (field: string, input: PrimitiveType | Validated<Value, Options>, options: Options) => MaySuccess<Value>): <const InputOptions extends Options>(inputOptions: InputOptions) => Validator<Value, InputOptions>;
77
- /**
78
- * 返回只进行基本检查,不带定制的验证逻辑的 validator。
79
- * 同时也是定制 validator 最小化实现的例子。
80
- */
81
- export declare const getAnyValidator: <const InputOptions extends CommonOptions<any>>(inputOptions: InputOptions) => Validator<unknown, InputOptions>;
82
- export {};
@@ -1,42 +0,0 @@
1
- import { success, failed } from '../lang/index.js';
2
- // -----------------------------------
3
- /**
4
- * 返回支持指定格式的 options、并按照传入的逻辑进行验证的 validator 的生成器。
5
- * 对 CommonOptions 相关内容的验证以自动包含在里面,只需要传入额外的验证逻辑即可。
6
- */
7
- export function getValidatorGenerator(validate) {
8
- return function validatorGenerator(inputOptions) {
9
- function validator(field, input) {
10
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
11
- const { null: allowNull = false, required = true, defaults, custom } = inputOptions;
12
- if (typeof field !== 'string') {
13
- input = field;
14
- field = 'value';
15
- }
16
- let value = input;
17
- if (typeof value === 'undefined') {
18
- if (typeof defaults !== 'undefined') {
19
- value = defaults;
20
- }
21
- else if (required) {
22
- return failed(`${field} is required`);
23
- }
24
- }
25
- if (value === null && !allowNull)
26
- return failed(`${field} cannot be null`);
27
- if (value === null || value === undefined)
28
- return success(value);
29
- const validated = validate(field, value, inputOptions);
30
- return validated.success && custom ? custom(validated.data) : validated;
31
- }
32
- return validator;
33
- };
34
- }
35
- // -----------------------------------
36
- /**
37
- * 返回只进行基本检查,不带定制的验证逻辑的 validator。
38
- * 同时也是定制 validator 最小化实现的例子。
39
- */
40
- export const getAnyValidator = getValidatorGenerator(function validate(field, input) {
41
- return success(input);
42
- });
@@ -1,3 +0,0 @@
1
- import { type CommonOptions } from './base.js';
2
- export type BooleanOptions = CommonOptions<boolean>;
3
- export declare const getBooleanValidator: <const InputOptions extends BooleanOptions>(inputOptions: InputOptions) => import("./base.js").Validator<boolean, InputOptions>;
@@ -1,22 +0,0 @@
1
- import { success, failed } from '../lang/index.js';
2
- import { getValidatorGenerator } from './base.js';
3
- export const getBooleanValidator = getValidatorGenerator(function validate(field, input) {
4
- let value = null;
5
- if (typeof input === 'boolean') {
6
- value = input;
7
- }
8
- else if (typeof input === 'string') {
9
- const str = input.trim().toLowerCase();
10
- if (['1', 'true', 'on', 'yes'].includes(str))
11
- value = true;
12
- else if (['0', 'false', 'off', 'no'].includes(str))
13
- value = false;
14
- }
15
- else if (typeof input === 'number') {
16
- if (input === 1)
17
- value = true;
18
- else if (input === 0)
19
- value = false;
20
- }
21
- return value === null ? failed(`${field} must be true or false`) : success(value);
22
- });
@@ -1,12 +0,0 @@
1
- /**
2
- * 验证日期时间类型的值,依赖 dayjs
3
- */
4
- import { Dayjs } from 'dayjs';
5
- import { type CommonOptions } from './base.js';
6
- export interface DatetimeOptions extends CommonOptions<number> {
7
- dayjs?: boolean;
8
- }
9
- export type DatetimeValue<Options extends DatetimeOptions> = Options extends {
10
- dayjs: true;
11
- } ? Dayjs : Date;
12
- export declare function getDatetimeValidator<const Options extends DatetimeOptions>(options?: Options): import("./base.js").Validator<DatetimeValue<Options>, Options>;
@@ -1,30 +0,0 @@
1
- /**
2
- * 验证日期时间类型的值,依赖 dayjs
3
- */
4
- import dayjs, { Dayjs } from 'dayjs';
5
- import { success, failed } from '../lang/index.js';
6
- import { getValidatorGenerator } from './base.js';
7
- export function getDatetimeValidator(options = {}) {
8
- return getValidatorGenerator(function validate(field, value) {
9
- let dayjsValue;
10
- if (typeof value === 'number') {
11
- dayjsValue = dayjs.unix(value);
12
- if (!dayjsValue.isValid())
13
- return failed(`${field} must be a valid unix timestamp`);
14
- }
15
- else if (typeof value === 'string') {
16
- dayjsValue = dayjs(value);
17
- if (!dayjsValue.isValid())
18
- return failed(`${field} must be a valid datetime string`);
19
- }
20
- else if (value instanceof Date || value instanceof Dayjs) {
21
- dayjsValue = dayjs(value);
22
- if (!dayjsValue.isValid())
23
- return failed(`${field} must be a valid Date or Dayjs object`);
24
- }
25
- else {
26
- return failed(`${field} must be a datetime string or unix timestamp`);
27
- }
28
- return success((options.dayjs ? dayjsValue : dayjsValue.toDate()));
29
- })(options);
30
- }
@@ -1,70 +0,0 @@
1
- /**
2
- * 实现创建 validator 的快捷方式
3
- */
4
- import { type ArrayOptions, type TupleOptions } from './array.js';
5
- import { type Validator, type CommonOptions, type Validated } from './base.js';
6
- import { type BooleanOptions } from './boolean.js';
7
- import { type DatetimeOptions, type DatetimeValue } from './datetime.js';
8
- import { type NumberOptions, type NumberValueWithChoices } from './number.js';
9
- import { type RecordOptions, type StructOptions } from './object.js';
10
- import { type OneOfOptions } from './one-of.js';
11
- import { type StringOptions, type StringValueWithChoices } from './string.js';
12
- export interface AnyDefinition extends CommonOptions {
13
- type: 'any';
14
- }
15
- export interface BooleanDefinition extends BooleanOptions {
16
- type: 'boolean';
17
- }
18
- export interface NumberDefinition extends NumberOptions {
19
- type: 'number';
20
- }
21
- export interface StringDefinition extends StringOptions {
22
- type: 'string';
23
- }
24
- export interface DatetimeDefinition extends DatetimeOptions {
25
- type: 'datetime';
26
- }
27
- export interface ArrayDefinition extends Omit<ArrayOptions, 'item'> {
28
- type: 'array';
29
- item: Definition;
30
- }
31
- export interface TupleDefinition extends Omit<TupleOptions, 'tuple'> {
32
- type: 'tuple';
33
- tuple: Definition[];
34
- }
35
- export interface StructDefinition extends Omit<StructOptions, 'struct'> {
36
- type: 'struct';
37
- struct: Record<string, Definition>;
38
- }
39
- export interface RecordDefinition extends Omit<RecordOptions, 'record'> {
40
- type: 'record';
41
- record: Definition;
42
- }
43
- export interface OneOfDefinition extends Omit<OneOfOptions, 'validators'> {
44
- type: 'oneOf';
45
- validators: Definition[];
46
- }
47
- export type Definition = AnyDefinition | BooleanDefinition | NumberDefinition | StringDefinition | DatetimeDefinition | ArrayDefinition | TupleDefinition | StructDefinition | RecordDefinition | OneOfDefinition;
48
- export type ValueOfDefinition<Def extends Definition> = Def extends AnyDefinition ? unknown : Def extends BooleanDefinition ? boolean : Def extends NumberDefinition ? NumberValueWithChoices<Def> : Def extends StringDefinition ? StringValueWithChoices<Def> : Def extends DatetimeDefinition ? DatetimeValue<Def> : Def extends ArrayDefinition ? Validated<ValueOfDefinition<Def['item']>, Def['item']>[] : Def extends TupleDefinition ? {
49
- [Key in keyof Def['tuple']]: Def['tuple'][Key] extends Definition ? Validated<ValueOfDefinition<Def['tuple'][Key]>, Def['tuple'][Key]> : Def['tuple'][Key];
50
- } : Def extends StructDefinition ? {
51
- [Key in keyof Def['struct']]: Validated<ValueOfDefinition<Def['struct'][Key]>, Def['struct'][Key]>;
52
- } : Def extends RecordDefinition ? Record<string, Validated<ValueOfDefinition<Def['record']>, Def['record']>> : Def extends OneOfDefinition ? {
53
- [Key in keyof Def['validators']]: Def['validators'][Key] extends Definition ? Validated<ValueOfDefinition<Def['validators'][Key]>, Def['validators'][Key]> : Def['validators'][Key];
54
- }[number] : never;
55
- export type OptionsFromDefinition<Def extends Definition> = Def extends ArrayDefinition ? Omit<Def, 'item'> & {
56
- item: ValidatorForDefinition<Def['item']>;
57
- } : Def extends TupleDefinition ? Omit<Def, 'tuple'> & {
58
- tuple: {
59
- [Key in keyof Def['tuple']]: Def['tuple'][Key] extends Definition ? ValidatorForDefinition<Def['tuple'][Key]> : never;
60
- };
61
- } : Def extends StructDefinition ? Omit<Def, 'struct'> & {
62
- struct: {
63
- [Key in keyof Def['struct']]: ValidatorForDefinition<Def['struct'][Key]>;
64
- };
65
- } : Def extends RecordDefinition ? Omit<Def, 'record'> & {
66
- record: ValidatorForDefinition<Def['record']>;
67
- } : Def;
68
- export type ValidatorForDefinition<Def extends Definition> = Validator<ValueOfDefinition<Def>, OptionsFromDefinition<Def>>;
69
- export type ResultForDefinition<Def extends Definition> = ReturnType<ValidatorForDefinition<Def>>;
70
- export declare function getValidator<const InputDefinition extends Definition>(definition: InputDefinition): ValidatorForDefinition<InputDefinition>;
@@ -1,121 +0,0 @@
1
- /**
2
- * 实现创建 validator 的快捷方式
3
- */
4
- import { getArrayValidator, getTupleValidator, } from './array.js';
5
- import { getAnyValidator } from './base.js';
6
- import { getBooleanValidator } from './boolean.js';
7
- import { getDatetimeValidator } from './datetime.js';
8
- import { getNumberValidator } from './number.js';
9
- import { getRecordValidator, getStructValidator, } from './object.js';
10
- import { getOneOfValidator } from './one-of.js';
11
- import { getStringValidator } from './string.js';
12
- export function getValidator(definition) {
13
- switch (definition.type) {
14
- case 'any':
15
- return getAnyValidator(definition);
16
- case 'boolean':
17
- return getBooleanValidator(definition);
18
- case 'number':
19
- return getNumberValidator(definition);
20
- case 'string':
21
- return getStringValidator(definition);
22
- case 'datetime':
23
- return getDatetimeValidator(definition);
24
- case 'array':
25
- // @ts-ignore 允许递归类型推断
26
- return getArrayValidator({
27
- // @ts-ignore 允许递归类型推断
28
- ...definition,
29
- item: getValidator(definition.item),
30
- });
31
- case 'tuple':
32
- return getTupleValidator({
33
- ...definition,
34
- tuple: definition.tuple.map(def => getValidator(def)),
35
- });
36
- case 'struct': {
37
- const struct = {};
38
- for (const [key, def] of Object.entries(definition.struct))
39
- struct[key] = getValidator(def);
40
- return getStructValidator({ ...definition, struct });
41
- }
42
- case 'record':
43
- return getRecordValidator({
44
- ...definition,
45
- record: getValidator(definition.record),
46
- });
47
- case 'oneOf':
48
- return getOneOfValidator({
49
- ...definition,
50
- validators: definition.validators.map(def => getValidator(def)),
51
- });
52
- }
53
- }
54
- // ---------------- 测试用例 -----------------
55
- // const v1 = getValidator({ type: 'string' })(1)
56
- // const v2 = getValidator({ type: 'string', null: true })(1)
57
- // const v3 = getValidator({ type: 'string', null: true, required: false })(1)
58
- // const v4 = getValidator({ type: 'string', null: true, required: false, choices: ['a', 'b', 'c'] })(
59
- // 1,
60
- // )
61
- // const v5 = getValidator({
62
- // type: 'string',
63
- // null: true,
64
- // required: false,
65
- // choices: ['a', 'b', 'c'],
66
- // defaults: 'd',
67
- // })(1)
68
- // const v6 = getValidator({
69
- // type: 'array',
70
- // null: true,
71
- // required: false,
72
- // item: { type: 'string', null: true, choices: ['a', 'b', 'c'] },
73
- // })(1)
74
- // const v7 = getValidator({
75
- // type: 'tuple',
76
- // tuple: [
77
- // { type: 'string', choices: ['a', 'b', 'c'] },
78
- // { type: 'string', null: true },
79
- // ],
80
- // })(1)
81
- // if (v7.success) {
82
- // const [a, b] = v7.data
83
- // }
84
- // const v8 = getValidator({
85
- // type: 'struct',
86
- // struct: {
87
- // x: { type: 'string', choices: ['a', 'b', 'c'] },
88
- // y: { type: 'string', null: true },
89
- // },
90
- // })(1)
91
- // if (v8.success) {
92
- // const { x, y } = v8.data
93
- // }
94
- // const v9 = getValidator({
95
- // type: 'record',
96
- // record: { type: 'string', null: true, choices: ['a', 'b', 'c'] },
97
- // })(1)
98
- // const v10 = getValidator({
99
- // type: 'oneOf',
100
- // validators: [
101
- // { type: 'string', choices: ['a', 'b', 'c'] },
102
- // { type: 'number', null: true },
103
- // ],
104
- // defaults: true,
105
- // })(1)
106
- // const v11 = getValidator({
107
- // type: 'string',
108
- // custom(value) {
109
- // return { success: true, data: value }
110
- // },
111
- // defaults: 'some text',
112
- // })(1)
113
- // const v12 = getValidator({
114
- // type: 'datetime',
115
- // null: true,
116
- // required: false,
117
- // })(1)
118
- // const v13 = getValidator({
119
- // type: 'datetime',
120
- // raw: true,
121
- // })(1)
@@ -1,9 +0,0 @@
1
- export * from './base.js';
2
- export * from './boolean.js';
3
- export * from './number.js';
4
- export * from './string.js';
5
- export * from './datetime.js';
6
- export * from './array.js';
7
- export * from './object.js';
8
- export * from './one-of.js';
9
- export * from './factory.js';
@@ -1,9 +0,0 @@
1
- export * from './base.js';
2
- export * from './boolean.js';
3
- export * from './number.js';
4
- export * from './string.js';
5
- export * from './datetime.js';
6
- export * from './array.js';
7
- export * from './object.js';
8
- export * from './one-of.js';
9
- export * from './factory.js';
@@ -1,19 +0,0 @@
1
- import { type CommonOptions } from './base.js';
2
- export interface NumberOptions extends CommonOptions<number> {
3
- /** 数值最小值 */
4
- min?: number;
5
- /** 数值最大值 */
6
- max?: number;
7
- /** 是否允许小数 @default false */
8
- float?: boolean;
9
- /**
10
- * 指定可选值
11
- * 若指定,前几个选项将不再生效 */
12
- choices?: number[] | Record<number, string>;
13
- }
14
- export type NumberValueWithChoices<Options extends NumberOptions> = Options extends {
15
- choices: (infer T)[];
16
- } ? T : Options extends {
17
- choices: Record<number, string>;
18
- } ? Options['choices'][keyof Options['choices']] : number;
19
- export declare function getNumberValidator<const Options extends NumberOptions>(options?: Options): import("./base.js").Validator<NumberValueWithChoices<Options>, Options>;