@wener/common 2.0.3 → 2.0.6
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/lib/ai/qwen3vl/index.js +1 -1
- package/lib/ai/qwen3vl/utils.js +15 -15
- package/lib/ai/qwen3vl/utils.js.map +1 -1
- package/lib/ai/vision/DocLayoutElementTypeSchema.js +22 -22
- package/lib/ai/vision/ImageAnnotationSchema.js +63 -47
- package/lib/ai/vision/index.js +2 -2
- package/lib/ai/vision/resolveImageAnnotation.js +81 -95
- package/lib/cn/ChineseResidentIdNo.js +55 -41
- package/lib/cn/ChineseResidentIdNo.js.map +1 -1
- package/lib/cn/ChineseResidentIdNo.mod.js +6 -1
- package/lib/cn/ChineseResidentIdNo.test.js +22 -21
- package/lib/cn/DivisionCode.js +220 -235
- package/lib/cn/DivisionCode.mod.js +6 -1
- package/lib/cn/DivisionCode.test.js +92 -121
- package/lib/cn/Mod11.js +18 -37
- package/lib/cn/Mod11.js.map +1 -1
- package/lib/cn/Mod31.js +23 -41
- package/lib/cn/UnifiedSocialCreditCode.js +143 -137
- package/lib/cn/UnifiedSocialCreditCode.mod.js +6 -1
- package/lib/cn/UnifiedSocialCreditCode.test.js +21 -15
- package/lib/cn/formatChineseAmount.js +46 -71
- package/lib/cn/index.js +6 -6
- package/lib/cn/mod.js +5 -3
- package/lib/cn/parseChineseNumber.js +81 -85
- package/lib/cn/parseChineseNumber.test.js +183 -261
- package/lib/cn/pinyin/cartesianProduct.js +19 -19
- package/lib/cn/pinyin/cartesianProduct.test.js +78 -178
- package/lib/cn/pinyin/loader.js +13 -11
- package/lib/cn/pinyin/preload.js +2 -1
- package/lib/cn/pinyin/toPinyin.test.js +149 -161
- package/lib/cn/pinyin/toPinyinPure.js +28 -23
- package/lib/cn/pinyin/transform.js +11 -11
- package/lib/cn/types.d.js +2 -2
- package/lib/consola/createStandardConsolaReporter.js +14 -15
- package/lib/consola/formatLogObject.js +149 -133
- package/lib/consola/formatLogObject.js.map +1 -1
- package/lib/consola/formatLogObject.test.js +167 -178
- package/lib/consola/index.js +2 -2
- package/lib/data/formatSort.js +14 -12
- package/lib/data/formatSort.test.js +33 -33
- package/lib/data/index.js +3 -3
- package/lib/data/maybeNumber.js +23 -23
- package/lib/data/maybeNumber.js.map +1 -1
- package/lib/data/parseSort.js +75 -68
- package/lib/data/parseSort.test.js +196 -187
- package/lib/data/resolvePagination.js +38 -39
- package/lib/data/resolvePagination.test.js +228 -218
- package/lib/data/types.d.js +2 -2
- package/lib/data/types.d.js.map +1 -1
- package/lib/dayjs/dayjs.js +20 -20
- package/lib/dayjs/formatDuration.js +56 -56
- package/lib/dayjs/formatDuration.js.map +1 -1
- package/lib/dayjs/formatDuration.test.js +63 -77
- package/lib/dayjs/index.js +4 -4
- package/lib/dayjs/parseDuration.js +21 -26
- package/lib/dayjs/parseRelativeTime.js +65 -66
- package/lib/dayjs/parseRelativeTime.test.js +227 -243
- package/lib/dayjs/resolveRelativeTime.js +74 -144
- package/lib/dayjs/resolveRelativeTime.js.map +1 -1
- package/lib/dayjs/resolveRelativeTime.test.js +296 -307
- package/lib/decimal/index.js +1 -1
- package/lib/decimal/parseDecimal.js +12 -12
- package/lib/drain3/Drain.js +321 -0
- package/lib/drain3/Drain.js.map +1 -0
- package/lib/drain3/LogCluster.js +38 -0
- package/lib/drain3/LogCluster.js.map +1 -0
- package/lib/drain3/Node.js +39 -0
- package/lib/drain3/Node.js.map +1 -0
- package/lib/drain3/TemplateMiner.js +205 -0
- package/lib/drain3/TemplateMiner.js.map +1 -0
- package/lib/drain3/index.js +31 -0
- package/lib/drain3/index.js.map +1 -0
- package/lib/drain3/persistence/FilePersistence.js +24 -0
- package/lib/drain3/persistence/FilePersistence.js.map +1 -0
- package/lib/drain3/persistence/MemoryPersistence.js +18 -0
- package/lib/drain3/persistence/MemoryPersistence.js.map +1 -0
- package/lib/drain3/persistence/PersistenceHandler.js +5 -0
- package/lib/drain3/persistence/PersistenceHandler.js.map +1 -0
- package/lib/drain3/types.js +7 -0
- package/lib/drain3/types.js.map +1 -0
- package/lib/emittery/emitter.js +7 -7
- package/lib/emittery/index.js +1 -1
- package/lib/foundation/schema/SexType.js +15 -12
- package/lib/foundation/schema/index.js +1 -1
- package/lib/foundation/schema/parseSexType.js +15 -16
- package/lib/foundation/schema/types.js +8 -6
- package/lib/fs/FileSystemError.js +18 -18
- package/lib/fs/IFileSystem.d.js +2 -2
- package/lib/fs/IFileSystem.d.js.map +1 -1
- package/lib/fs/MemoryFileSystem.test.js +172 -181
- package/lib/fs/createBrowserFileSystem.js +222 -233
- package/lib/fs/createBrowserFileSystem.js.map +1 -1
- package/lib/fs/createMemoryFileSystem.js +473 -510
- package/lib/fs/createMemoryFileSystem.js.map +1 -1
- package/lib/fs/createSandboxFileSystem.js +102 -101
- package/lib/fs/createSandboxFileSystem.js.map +1 -1
- package/lib/fs/createWebDavFileSystem.js +162 -132
- package/lib/fs/createWebDavFileSystem.js.map +1 -1
- package/lib/fs/createWebFileSystem.js +202 -0
- package/lib/fs/createWebFileSystem.js.map +1 -0
- package/lib/fs/findMimeType.js +14 -14
- package/lib/fs/findMimeType.js.map +1 -1
- package/lib/fs/index.js +7 -7
- package/lib/fs/index.js.map +1 -1
- package/lib/fs/minio/createMinioFileSystem.js +977 -0
- package/lib/fs/minio/createMinioFileSystem.js.map +1 -0
- package/lib/fs/minio/index.js +2 -0
- package/lib/fs/minio/index.js.map +1 -0
- package/lib/fs/orpc/FileSystemContract.js +57 -57
- package/lib/fs/orpc/createContractClientFileSystem.js +88 -88
- package/lib/fs/orpc/createContractClientFileSystem.js.map +1 -1
- package/lib/fs/orpc/index.js +2 -2
- package/lib/fs/orpc/server/createFileSystemContractImpl.js +62 -60
- package/lib/fs/orpc/server/createFileSystemContractImpl.js.map +1 -1
- package/lib/fs/orpc/server/index.js +1 -1
- package/lib/fs/s3/createS3MiniFileSystem.js +756 -689
- package/lib/fs/s3/createS3MiniFileSystem.js.map +1 -1
- package/lib/fs/s3/index.js +1 -1
- package/lib/fs/s3/s3mini.test.js +524 -553
- package/lib/fs/scandir.js +56 -56
- package/lib/fs/server/createDatabaseFileSystem.js +834 -741
- package/lib/fs/server/createDatabaseFileSystem.js.map +1 -1
- package/lib/fs/server/createNodeFileSystem.js +407 -380
- package/lib/fs/server/createNodeFileSystem.js.map +1 -1
- package/lib/fs/server/dbfs.test.js +201 -214
- package/lib/fs/server/index.js +1 -1
- package/lib/fs/server/loadTestDatabase.js +40 -43
- package/lib/fs/tests/runFileSystemTest.js +352 -315
- package/lib/fs/tests/runFileSystemTest.js.map +1 -1
- package/lib/fs/types.js +17 -20
- package/lib/fs/utils/getFileUrl.js +24 -30
- package/lib/fs/utils.js +17 -17
- package/lib/fs/utils.js.map +1 -1
- package/lib/fs/webdav/index.js +2 -0
- package/lib/fs/webdav/index.js.map +1 -0
- package/lib/index.js +2 -2
- package/lib/jsonschema/JsonSchema.js +216 -155
- package/lib/jsonschema/JsonSchema.js.map +1 -1
- package/lib/jsonschema/JsonSchema.test.js +123 -124
- package/lib/jsonschema/forEachJsonSchema.js +41 -41
- package/lib/jsonschema/forEachJsonSchema.js.map +1 -1
- package/lib/jsonschema/index.js +2 -2
- package/lib/jsonschema/types.d.js +2 -2
- package/lib/jsonschema/types.d.js.map +1 -1
- package/lib/meta/defineFileType.js +32 -38
- package/lib/meta/defineInit.js +39 -35
- package/lib/meta/defineMetadata.js +37 -34
- package/lib/meta/defineMetadata.js.map +1 -1
- package/lib/meta/defineMetadata.test.js +13 -12
- package/lib/meta/index.js +3 -3
- package/lib/orpc/createOpenApiContractClient.js +26 -24
- package/lib/orpc/createOpenApiContractClient.js.map +1 -1
- package/lib/orpc/createRpcContractClient.js +37 -31
- package/lib/orpc/index.js +2 -2
- package/lib/orpc/resolveLinkPlugins.js +25 -25
- package/lib/password/PHC.js +187 -189
- package/lib/password/PHC.js.map +1 -1
- package/lib/password/PHC.test.js +517 -535
- package/lib/password/Password.js +85 -80
- package/lib/password/Password.test.js +330 -364
- package/lib/password/createArgon2PasswordAlgorithm.js +50 -51
- package/lib/password/createArgon2PasswordAlgorithm.js.map +1 -1
- package/lib/password/createBase64PasswordAlgorithm.js +11 -11
- package/lib/password/createBase64PasswordAlgorithm.js.map +1 -1
- package/lib/password/createBcryptPasswordAlgorithm.js +20 -18
- package/lib/password/createBcryptPasswordAlgorithm.js.map +1 -1
- package/lib/password/createPBKDF2PasswordAlgorithm.js +65 -52
- package/lib/password/createPBKDF2PasswordAlgorithm.js.map +1 -1
- package/lib/password/createScryptPasswordAlgorithm.js +74 -63
- package/lib/password/createScryptPasswordAlgorithm.js.map +1 -1
- package/lib/password/index.js +5 -5
- package/lib/password/server/index.js +1 -1
- package/lib/resource/Identifiable.js +2 -2
- package/lib/resource/ListQuery.js +42 -42
- package/lib/resource/ListQuery.js.map +1 -1
- package/lib/resource/getTitleOfResource.js +5 -5
- package/lib/resource/index.js +2 -2
- package/lib/resource/index.js.map +1 -1
- package/lib/resource/schema/AnyResourceSchema.js +91 -89
- package/lib/resource/schema/BaseResourceSchema.js +26 -26
- package/lib/resource/schema/ResourceActionType.js +117 -115
- package/lib/resource/schema/ResourceStatus.js +94 -92
- package/lib/resource/schema/ResourceType.js +25 -23
- package/lib/resource/schema/index.js +5 -5
- package/lib/resource/schema/types.js +86 -55
- package/lib/resource/schema/types.test.js +16 -13
- package/lib/s3/formatS3Url.js +60 -60
- package/lib/s3/formatS3Url.js.map +1 -1
- package/lib/s3/formatS3Url.test.js +238 -261
- package/lib/s3/index.js +2 -2
- package/lib/s3/parseS3Url.js +61 -60
- package/lib/s3/parseS3Url.js.map +1 -1
- package/lib/s3/parseS3Url.test.js +270 -269
- package/lib/schema/SchemaRegistry.js +41 -42
- package/lib/schema/SchemaRegistry.js.map +1 -1
- package/lib/schema/SchemaRegistry.mod.js +1 -1
- package/lib/schema/TypeSchema.d.js +2 -2
- package/lib/schema/TypeSchema.d.js.map +1 -1
- package/lib/schema/createSchemaData.js +113 -67
- package/lib/schema/createSchemaData.js.map +1 -1
- package/lib/schema/findJsonSchemaByPath.js +28 -23
- package/lib/schema/findJsonSchemaByPath.js.map +1 -1
- package/lib/schema/formatZodError.js +113 -134
- package/lib/schema/formatZodError.js.map +1 -1
- package/lib/schema/formatZodError.test.js +192 -195
- package/lib/schema/getSchemaCache.js +7 -7
- package/lib/schema/getSchemaOptions.js +17 -16
- package/lib/schema/index.js +6 -6
- package/lib/schema/toJsonSchema.js +196 -190
- package/lib/schema/toJsonSchema.js.map +1 -1
- package/lib/schema/toJsonSchema.test.js +34 -26
- package/lib/schema/validate.js +106 -97
- package/lib/schema/validate.js.map +1 -1
- package/lib/tools/generateSchema.js +40 -40
- package/lib/tools/renderJsonSchemaToMarkdownDoc.js +74 -74
- package/lib/utils/buildBaseUrl.js +8 -8
- package/lib/utils/buildRedactorFormSchema.js +55 -54
- package/lib/utils/buildRedactorFormSchema.js.map +1 -1
- package/lib/utils/getEstimateProcessTime.js +24 -19
- package/lib/utils/index.js +3 -3
- package/lib/utils/resolveFeatureOptions.js +9 -9
- package/package.json +37 -18
- package/src/ai/qwen3vl/utils.ts +1 -1
- package/src/ai/vision/index.ts +2 -2
- package/src/cn/ChineseResidentIdNo.ts +1 -1
- package/src/cn/Mod11.ts +1 -1
- package/src/cn/__snapshots__/ChineseResidentIdNo.test.ts.snap +1 -1
- package/src/cn/__snapshots__/UnifiedSocialCreditCode.test.ts.snap +0 -23
- package/src/cn/index.ts +1 -2
- package/src/cn/parseChineseNumber.test.ts +4 -4
- package/src/consola/formatLogObject.ts +6 -6
- package/src/consola/index.ts +1 -1
- package/src/data/index.ts +3 -4
- package/src/data/maybeNumber.ts +1 -1
- package/src/data/parseSort.test.ts +0 -1
- package/src/data/resolvePagination.ts +2 -2
- package/src/data/types.d.ts +2 -2
- package/src/dayjs/formatDuration.ts +10 -11
- package/src/dayjs/index.ts +1 -1
- package/src/dayjs/parseRelativeTime.ts +1 -1
- package/src/dayjs/resolveRelativeTime.ts +11 -14
- package/src/drain3/Drain.test.ts +378 -0
- package/src/drain3/Drain.ts +394 -0
- package/src/drain3/LogCluster.ts +46 -0
- package/src/drain3/Node.ts +53 -0
- package/src/drain3/TemplateMiner.ts +246 -0
- package/src/drain3/index.ts +34 -0
- package/src/drain3/persistence/FilePersistence.ts +24 -0
- package/src/drain3/persistence/MemoryPersistence.ts +23 -0
- package/src/drain3/persistence/PersistenceHandler.ts +19 -0
- package/src/drain3/types.ts +75 -0
- package/src/fs/IFileSystem.d.ts +1 -2
- package/src/fs/createBrowserFileSystem.ts +7 -5
- package/src/fs/createMemoryFileSystem.ts +9 -13
- package/src/fs/createSandboxFileSystem.ts +1 -1
- package/src/fs/createWebDavFileSystem.ts +30 -17
- package/src/fs/createWebFileSystem.ts +242 -0
- package/src/fs/findMimeType.ts +1 -4
- package/src/fs/index.ts +5 -5
- package/src/fs/minio/createMinioFileSystem.ts +1148 -0
- package/src/fs/minio/index.ts +1 -0
- package/src/fs/orpc/createContractClientFileSystem.ts +5 -5
- package/src/fs/orpc/server/createFileSystemContractImpl.ts +1 -1
- package/src/fs/s3/createS3MiniFileSystem.ts +120 -79
- package/src/fs/s3/s3fs.test.ts +441 -0
- package/src/fs/s3/s3mini.test.ts +2 -2
- package/src/fs/server/createDatabaseFileSystem.ts +78 -114
- package/src/fs/server/createNodeFileSystem.ts +32 -13
- package/src/fs/server/dbfs.test.ts +13 -8
- package/src/fs/server/index.ts +1 -0
- package/src/fs/server/loadTestDatabase.ts +8 -119
- package/src/fs/tests/runFileSystemTest.ts +29 -28
- package/src/fs/utils.ts +1 -1
- package/src/fs/webdav/index.ts +1 -0
- package/src/jsonschema/JsonSchema.ts +5 -5
- package/src/jsonschema/forEachJsonSchema.ts +1 -1
- package/src/jsonschema/index.ts +1 -1
- package/src/jsonschema/types.d.ts +1 -1
- package/src/meta/defineMetadata.ts +1 -1
- package/src/meta/index.ts +2 -3
- package/src/orm/createSqliteDialect.ts +17 -0
- package/src/orm/index.ts +1 -0
- package/src/orpc/createOpenApiContractClient.ts +3 -3
- package/src/orpc/index.ts +1 -1
- package/src/password/PHC.ts +3 -3
- package/src/password/createArgon2PasswordAlgorithm.ts +2 -2
- package/src/password/createBase64PasswordAlgorithm.ts +2 -2
- package/src/password/createBcryptPasswordAlgorithm.ts +4 -2
- package/src/password/createPBKDF2PasswordAlgorithm.ts +2 -2
- package/src/password/createScryptPasswordAlgorithm.ts +4 -4
- package/src/password/index.ts +2 -2
- package/src/resource/ListQuery.ts +4 -1
- package/src/resource/index.ts +3 -3
- package/src/resource/schema/index.ts +4 -4
- package/src/s3/formatS3Url.test.ts +1 -1
- package/src/s3/formatS3Url.ts +2 -2
- package/src/s3/index.ts +1 -1
- package/src/s3/parseS3Url.ts +1 -1
- package/src/schema/SchemaRegistry.ts +2 -2
- package/src/schema/TypeSchema.d.ts +6 -6
- package/src/schema/createSchemaData.ts +5 -5
- package/src/schema/findJsonSchemaByPath.ts +5 -5
- package/src/schema/formatZodError.test.ts +2 -1
- package/src/schema/formatZodError.ts +50 -62
- package/src/schema/index.ts +5 -5
- package/src/schema/toJsonSchema.ts +6 -6
- package/src/schema/validate.ts +2 -2
- package/src/utils/buildRedactorFormSchema.ts +4 -4
- package/src/utils/formatNumber.ts +18 -0
- package/src/utils/formatPercent.ts +17 -0
- package/src/utils/index.ts +3 -3
- package/src/utils/resolveFeatureOptions.ts +1 -1
|
@@ -10,23 +10,23 @@ import type { JsonSchemaDef } from '../jsonschema';
|
|
|
10
10
|
export type TypeSchema<I = unknown, O = I> = TSchema | z.ZodSchema<O, I> | JsonSchemaDef | StandardSchemaV1<I, O>;
|
|
11
11
|
|
|
12
12
|
export type SchemaOutput<S extends TypeSchema> =
|
|
13
|
-
S extends StandardSchemaV1<infer
|
|
13
|
+
S extends StandardSchemaV1<infer _I, infer O>
|
|
14
14
|
? O
|
|
15
|
-
: S extends z.ZodSchema<infer O, infer
|
|
15
|
+
: S extends z.ZodSchema<infer O, infer _I>
|
|
16
16
|
? O
|
|
17
17
|
: S extends TSchema
|
|
18
18
|
? TypeBoxStaticEncode<S>
|
|
19
|
-
: S extends JsonSchemaDef<infer
|
|
19
|
+
: S extends JsonSchemaDef<infer _I, infer O>
|
|
20
20
|
? O
|
|
21
21
|
: never;
|
|
22
22
|
|
|
23
23
|
export type SchemaInput<S extends TypeSchema> =
|
|
24
|
-
S extends StandardSchemaV1<infer I, infer
|
|
24
|
+
S extends StandardSchemaV1<infer I, infer _O>
|
|
25
25
|
? I
|
|
26
|
-
: S extends z.ZodSchema<infer
|
|
26
|
+
: S extends z.ZodSchema<infer _O, infer I>
|
|
27
27
|
? I
|
|
28
28
|
: S extends TSchema
|
|
29
29
|
? TypeBoxStaticDecode<S>
|
|
30
|
-
: S extends JsonSchemaDef<infer I, infer
|
|
30
|
+
: S extends JsonSchemaDef<infer I, infer _O>
|
|
31
31
|
? I
|
|
32
32
|
: never;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { match, P } from 'ts-pattern';
|
|
2
2
|
import type { JsonSchemaDef } from '../jsonschema';
|
|
3
|
-
import { toJsonSchema } from './toJsonSchema';
|
|
4
3
|
import type { SchemaOutput, TypeSchema } from './TypeSchema';
|
|
4
|
+
import { toJsonSchema } from './toJsonSchema';
|
|
5
5
|
|
|
6
6
|
export function createSchemaData<S extends TypeSchema>(
|
|
7
7
|
ts: S,
|
|
@@ -54,8 +54,8 @@ function _create(schema: JsonSchemaDef, options: CreateOptions, ctx: { required:
|
|
|
54
54
|
.with({ oneOf: P.nonNullable }, (schema) => {
|
|
55
55
|
return _create(schema.oneOf[0], options, { required: false });
|
|
56
56
|
})
|
|
57
|
-
.with({ type: 'string' }, (
|
|
58
|
-
.with({ type: P.union('number', 'integer') }, (
|
|
57
|
+
.with({ type: 'string' }, (_schema) => '')
|
|
58
|
+
.with({ type: P.union('number', 'integer') }, (_schema) => 0)
|
|
59
59
|
.with({ type: 'object' }, () => {
|
|
60
60
|
const out: Record<string, any> = {};
|
|
61
61
|
|
|
@@ -73,8 +73,8 @@ function _create(schema: JsonSchemaDef, options: CreateOptions, ctx: { required:
|
|
|
73
73
|
return out;
|
|
74
74
|
})
|
|
75
75
|
.with({ type: 'null' }, () => null)
|
|
76
|
-
.with({ type: 'boolean' }, (
|
|
77
|
-
.with({ type: 'array' }, (
|
|
76
|
+
.with({ type: 'boolean' }, (_schema) => false)
|
|
77
|
+
.with({ type: 'array' }, (_schema) => [])
|
|
78
78
|
.otherwise(() => {
|
|
79
79
|
return undefined;
|
|
80
80
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { firstOfMaybeArray } from '@wener/utils';
|
|
2
|
-
import { toJsonSchema } from './toJsonSchema';
|
|
3
2
|
import type { TypeSchema } from './TypeSchema';
|
|
3
|
+
import { toJsonSchema } from './toJsonSchema';
|
|
4
4
|
|
|
5
5
|
export function findJsonSchemaByPath(schema: TypeSchema, objectPath: string) {
|
|
6
6
|
schema = toJsonSchema(schema);
|
|
@@ -14,10 +14,10 @@ export function findJsonSchemaByPath(schema: TypeSchema, objectPath: string) {
|
|
|
14
14
|
for (const segment of segments) {
|
|
15
15
|
// 检查当前 schema 是否是对象类型且有 properties
|
|
16
16
|
if (
|
|
17
|
-
currentSchema
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
currentSchema &&
|
|
18
|
+
typeof currentSchema === 'object' &&
|
|
19
|
+
currentSchema.properties &&
|
|
20
|
+
currentSchema.properties[segment]
|
|
21
21
|
) {
|
|
22
22
|
currentSchema = currentSchema.properties[segment];
|
|
23
23
|
continue;
|
|
@@ -181,10 +181,11 @@ describe('formatZodError', () => {
|
|
|
181
181
|
|
|
182
182
|
it('should use schema description when available', () => {
|
|
183
183
|
const schema = z.object({
|
|
184
|
-
name: z.string().describe('姓名'),
|
|
184
|
+
name: z.string().min(1).describe('姓名'),
|
|
185
185
|
email: z.string().email().describe('邮箱地址'),
|
|
186
186
|
});
|
|
187
187
|
|
|
188
|
+
// Use empty string for name (triggers min(1) error) and invalid email
|
|
188
189
|
const result = schema.safeParse({ name: '', email: 'invalid' });
|
|
189
190
|
expect(result.success).toBe(false);
|
|
190
191
|
if (!result.success) {
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { ZodError } from 'zod/v4';
|
|
1
|
+
import type { core, ZodError } from 'zod/v4';
|
|
2
2
|
import { findJsonSchemaByPath } from './findJsonSchemaByPath';
|
|
3
3
|
import type { TypeSchema } from './TypeSchema';
|
|
4
4
|
|
|
5
|
+
// Zod 4 issue types with proper typing
|
|
6
|
+
type ZodIssue = core.$ZodIssue;
|
|
7
|
+
type ZodIssueInvalidType = core.$ZodIssueInvalidType;
|
|
8
|
+
type ZodIssueTooSmall = core.$ZodIssueTooSmall;
|
|
9
|
+
type ZodIssueTooBig = core.$ZodIssueTooBig;
|
|
10
|
+
type ZodIssueInvalidStringFormat = core.$ZodIssueInvalidStringFormat;
|
|
11
|
+
type ZodIssueInvalidValue = core.$ZodIssueInvalidValue;
|
|
12
|
+
type ZodIssueUnrecognizedKeys = core.$ZodIssueUnrecognizedKeys;
|
|
13
|
+
|
|
5
14
|
export function formatZodError(error: ZodError, schema?: TypeSchema): string {
|
|
6
15
|
if (!error.issues || error.issues.length === 0) {
|
|
7
16
|
return error.message || '验证失败';
|
|
@@ -34,102 +43,81 @@ export function formatZodError(error: ZodError, schema?: TypeSchema): string {
|
|
|
34
43
|
return messages.join(';');
|
|
35
44
|
}
|
|
36
45
|
|
|
37
|
-
function formatIssueMessage(issue:
|
|
46
|
+
function formatIssueMessage(issue: ZodIssue, _schema?: TypeSchema): string {
|
|
38
47
|
let message = issue.message;
|
|
39
48
|
|
|
40
49
|
// 处理常见的错误类型,生成更友好的消息
|
|
41
|
-
|
|
42
|
-
const code = issue.code as string;
|
|
43
|
-
switch (code) {
|
|
50
|
+
switch (issue.code) {
|
|
44
51
|
case 'invalid_type': {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (
|
|
52
|
+
const i = issue as ZodIssueInvalidType;
|
|
53
|
+
// Zod v4 doesn't have 'received' field directly, extract from message
|
|
54
|
+
const match = issue.message.match(/received (\w+)/);
|
|
55
|
+
const received = match?.[1];
|
|
56
|
+
if (received === 'undefined') {
|
|
50
57
|
message = '必填';
|
|
51
|
-
} else if (
|
|
58
|
+
} else if (received === 'null') {
|
|
52
59
|
message = '不能为空';
|
|
53
60
|
} else {
|
|
54
|
-
message = issue.message || `期望类型 ${
|
|
61
|
+
message = issue.message || `期望类型 ${i.expected},但收到 ${received}`;
|
|
55
62
|
}
|
|
56
63
|
break;
|
|
57
64
|
}
|
|
58
|
-
case '
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
};
|
|
62
|
-
if (invalidStringIssue.validation === 'email') {
|
|
65
|
+
case 'invalid_format': {
|
|
66
|
+
const i = issue as ZodIssueInvalidStringFormat;
|
|
67
|
+
if (i.format === 'email') {
|
|
63
68
|
message = '请输入有效的邮箱地址';
|
|
64
|
-
} else if (
|
|
69
|
+
} else if (i.format === 'url') {
|
|
65
70
|
message = '请输入有效的 URL';
|
|
66
|
-
} else if (
|
|
71
|
+
} else if (i.format === 'uuid') {
|
|
67
72
|
message = '请输入有效的 UUID';
|
|
68
|
-
} else if (
|
|
73
|
+
} else if (i.format === 'date') {
|
|
69
74
|
message = '请输入有效的日期';
|
|
70
75
|
}
|
|
71
76
|
break;
|
|
72
77
|
}
|
|
73
78
|
case 'too_small': {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
minimum: number;
|
|
77
|
-
};
|
|
78
|
-
if (tooSmallIssue.type === 'string' && tooSmallIssue.minimum === 1) {
|
|
79
|
+
const i = issue as ZodIssueTooSmall;
|
|
80
|
+
if (i.origin === 'string' && i.minimum === 1) {
|
|
79
81
|
message = '不能为空';
|
|
80
|
-
} else if (
|
|
81
|
-
message = `至少需要 ${
|
|
82
|
-
} else if (
|
|
83
|
-
message = `至少需要 ${
|
|
82
|
+
} else if (i.origin === 'string') {
|
|
83
|
+
message = `至少需要 ${i.minimum} 个字符`;
|
|
84
|
+
} else if (i.origin === 'number' || i.origin === 'int') {
|
|
85
|
+
message = `至少需要 ${i.minimum}`;
|
|
86
|
+
} else if (i.origin === 'array') {
|
|
87
|
+
message = `至少需要 ${i.minimum} 项`;
|
|
84
88
|
}
|
|
85
89
|
break;
|
|
86
90
|
}
|
|
87
91
|
case 'too_big': {
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
maximum
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
message = `最多 ${tooBigIssue.maximum}`;
|
|
96
|
-
} else if (tooBigIssue.type === 'array') {
|
|
97
|
-
message = `最多 ${tooBigIssue.maximum} 项`;
|
|
92
|
+
const i = issue as ZodIssueTooBig;
|
|
93
|
+
if (i.origin === 'string') {
|
|
94
|
+
message = `最多 ${i.maximum} 个字符`;
|
|
95
|
+
} else if (i.origin === 'number' || i.origin === 'int') {
|
|
96
|
+
message = `最多 ${i.maximum}`;
|
|
97
|
+
} else if (i.origin === 'array') {
|
|
98
|
+
message = `最多 ${i.maximum} 项`;
|
|
98
99
|
}
|
|
99
100
|
break;
|
|
100
101
|
}
|
|
101
|
-
case '
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
case 'invalid_value': {
|
|
103
|
+
const i = issue as ZodIssueInvalidValue;
|
|
104
|
+
if (i.values.length === 1) {
|
|
105
|
+
// Single value means it's a literal check
|
|
106
|
+
message = `必须是 ${String(i.values[0])}`;
|
|
107
|
+
} else {
|
|
108
|
+
message = `必须是以下值之一: ${i.values.map(String).join(', ')}`;
|
|
109
|
+
}
|
|
106
110
|
break;
|
|
107
111
|
}
|
|
108
112
|
case 'unrecognized_keys': {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
};
|
|
112
|
-
message = `不支持的字段: ${unrecognizedIssue.keys?.join(', ') || '未知字段'}`;
|
|
113
|
+
const i = issue as ZodIssueUnrecognizedKeys;
|
|
114
|
+
message = `不支持的字段: ${i.keys.join(', ')}`;
|
|
113
115
|
break;
|
|
114
116
|
}
|
|
115
117
|
case 'invalid_union': {
|
|
116
118
|
message = '不符合任何允许的类型';
|
|
117
119
|
break;
|
|
118
120
|
}
|
|
119
|
-
case 'invalid_union_discriminator': {
|
|
120
|
-
const discriminatorIssue = issue as typeof issue & {
|
|
121
|
-
options: readonly unknown[];
|
|
122
|
-
};
|
|
123
|
-
message = `必须是以下值之一: ${discriminatorIssue.options?.map(String).join(', ') || '未知选项'}`;
|
|
124
|
-
break;
|
|
125
|
-
}
|
|
126
|
-
case 'invalid_literal': {
|
|
127
|
-
const literalIssue = issue as typeof issue & {
|
|
128
|
-
expected: unknown;
|
|
129
|
-
};
|
|
130
|
-
message = `必须是 ${String(literalIssue.expected)}`;
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
121
|
case 'custom': {
|
|
134
122
|
// 保留自定义错误消息
|
|
135
123
|
message = issue.message;
|
package/src/schema/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type * from './TypeSchema';
|
|
2
|
-
export { isJsonSchema, isZodSchema, isTypeBoxSchema, validate, parseData, type ValidationResult } from './validate';
|
|
3
|
-
export { getSchemaOptions, getSchemaOptionLabel } from './getSchemaOptions';
|
|
4
|
-
export { toJsonSchema } from './toJsonSchema';
|
|
5
|
-
export { findJsonSchemaByPath } from './findJsonSchemaByPath';
|
|
6
1
|
export { createSchemaData } from './createSchemaData';
|
|
2
|
+
export { findJsonSchemaByPath } from './findJsonSchemaByPath';
|
|
3
|
+
export { getSchemaOptionLabel, getSchemaOptions } from './getSchemaOptions';
|
|
7
4
|
export { SchemaRegistry } from './SchemaRegistry';
|
|
5
|
+
export type * from './TypeSchema';
|
|
6
|
+
export { toJsonSchema } from './toJsonSchema';
|
|
7
|
+
export { isJsonSchema, isTypeBoxSchema, isZodSchema, parseData, type ValidationResult, validate } from './validate';
|
|
@@ -33,7 +33,7 @@ export function toJsonSchema(schema: TypeSchema): JsonSchemaDef {
|
|
|
33
33
|
// prefer nullable
|
|
34
34
|
match(js)
|
|
35
35
|
.with({ anyOf: [P.select(), { type: 'null' }] }, (select) => {
|
|
36
|
-
delete js
|
|
36
|
+
delete js.anyOf;
|
|
37
37
|
Object.assign(js, select);
|
|
38
38
|
js.nullable = true;
|
|
39
39
|
})
|
|
@@ -70,9 +70,9 @@ function visit(js: JsonSchemaDef, f: (js: JsonSchemaDef) => void) {
|
|
|
70
70
|
const _visit = (
|
|
71
71
|
js: JsonSchemaDef,
|
|
72
72
|
f: (js: JsonSchemaDef) => void,
|
|
73
|
-
|
|
73
|
+
_parent: JsonSchemaDef | undefined,
|
|
74
74
|
path: string[],
|
|
75
|
-
|
|
75
|
+
_k?: string,
|
|
76
76
|
) => {
|
|
77
77
|
if (!js) {
|
|
78
78
|
return;
|
|
@@ -109,9 +109,9 @@ function visit(js: JsonSchemaDef, f: (js: JsonSchemaDef) => void) {
|
|
|
109
109
|
_visit(js, f, undefined, []);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
function
|
|
112
|
+
function _resolveJsonSchemaDef(
|
|
113
113
|
js: JsonSchemaDef,
|
|
114
|
-
|
|
114
|
+
_ctx?: {
|
|
115
115
|
parent: JsonSchemaDef;
|
|
116
116
|
key: string;
|
|
117
117
|
},
|
|
@@ -129,7 +129,7 @@ function resolveJsonSchemaDef(
|
|
|
129
129
|
for (const key in schema.properties) {
|
|
130
130
|
const prop = schema.properties[key];
|
|
131
131
|
if (prop) {
|
|
132
|
-
schema.properties[key] =
|
|
132
|
+
schema.properties[key] = _resolveJsonSchemaDef(prop, { parent: schema, key });
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
return schema;
|
package/src/schema/validate.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Kind as TypeBoxKind
|
|
1
|
+
import { type TSchema, Kind as TypeBoxKind } from '@sinclair/typebox';
|
|
2
2
|
import '@sinclair/typebox';
|
|
3
3
|
import { TypeCompiler } from '@sinclair/typebox/compiler';
|
|
4
4
|
import { ifPresent } from '@wener/utils';
|
|
@@ -107,7 +107,7 @@ export function parseData<S extends TypeSchema>(schema: S, data: unknown): Schem
|
|
|
107
107
|
);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
function
|
|
110
|
+
function _formatIssues(_schema: TypeSchema, _issues: Array<ValidationIssue>): string {
|
|
111
111
|
return '';
|
|
112
112
|
}
|
|
113
113
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { forEachJsonSchema, type JsonSchemaDef } from '../jsonschema';
|
|
2
|
-
import {
|
|
2
|
+
import { type TypeSchema, toJsonSchema } from '../schema';
|
|
3
3
|
|
|
4
4
|
export const RedactedText = '[redacted]';
|
|
5
5
|
|
|
@@ -60,10 +60,10 @@ export function buildRedactorFormSchema(
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
function
|
|
63
|
+
function _buildReversibleRedactText({
|
|
64
64
|
id,
|
|
65
|
-
type,
|
|
66
|
-
key,
|
|
65
|
+
type: _type,
|
|
66
|
+
key: _key,
|
|
67
67
|
timestamp,
|
|
68
68
|
}: {
|
|
69
69
|
id?: string | number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a number, removing trailing zeros
|
|
3
|
+
* @param value - number or string convertible to number
|
|
4
|
+
* @param decimals - decimal places to keep, default 2
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* formatNumber(1.50) // "1.5"
|
|
8
|
+
* formatNumber(1.00) // "1"
|
|
9
|
+
* formatNumber(1.234) // "1.23"
|
|
10
|
+
*/
|
|
11
|
+
export function formatNumber(value: number | string, decimals = 2): string {
|
|
12
|
+
const num = typeof value === 'string' ? Number.parseFloat(value) : value;
|
|
13
|
+
if (Number.isNaN(num)) return String(value);
|
|
14
|
+
return num
|
|
15
|
+
.toFixed(decimals)
|
|
16
|
+
.replace(/(\.\d*?)0+$/, '$1')
|
|
17
|
+
.replace(/\.$/, '');
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { formatNumber } from './formatNumber';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Format a percentage, removing trailing zeros
|
|
5
|
+
* @param value - number (0-1 or 0-100)
|
|
6
|
+
* @param decimals - decimal places to keep, default 2
|
|
7
|
+
* @param isRatio - whether value is a ratio (0-1), default false
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* formatPercent(0.5, 2, true) // "50"
|
|
11
|
+
* formatPercent(50.00) // "50"
|
|
12
|
+
* formatPercent(33.33) // "33.33"
|
|
13
|
+
*/
|
|
14
|
+
export function formatPercent(value: number, decimals = 2, isRatio = false): string {
|
|
15
|
+
const percent = isRatio ? value * 100 : value;
|
|
16
|
+
return formatNumber(percent, decimals);
|
|
17
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { buildBaseUrl } from './buildBaseUrl';
|
|
2
2
|
|
|
3
3
|
export { buildRedactorFormSchema } from './buildRedactorFormSchema';
|
|
4
|
-
|
|
5
|
-
export {
|
|
4
|
+
export { formatNumber } from './formatNumber';
|
|
5
|
+
export { getEstimateProcessTime } from './getEstimateProcessTime';
|