@hy_ong/zod-kit 0.2.0 → 0.2.1
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/.github/workflows/ci.yml +24 -0
- package/CLAUDE.md +64 -22
- package/dist/chunk-36NWHESN.js +124 -0
- package/dist/chunk-4LYZAO3P.js +165 -0
- package/dist/chunk-5GAZQDVS.cjs +206 -0
- package/dist/chunk-5LS4DSRQ.cjs +127 -0
- package/dist/chunk-5OGW2ERW.js +181 -0
- package/dist/chunk-5ZEKWPSE.cjs +69 -0
- package/dist/chunk-6OGDPSWT.js +135 -0
- package/dist/chunk-6X22I6NQ.cjs +136 -0
- package/dist/chunk-77KZUPPN.cjs +177 -0
- package/dist/chunk-AANSHH2O.cjs +165 -0
- package/dist/chunk-AI72FMOF.cjs +130 -0
- package/dist/chunk-AWV2IT66.js +146 -0
- package/dist/chunk-B3U5G3AA.js +160 -0
- package/dist/chunk-CFFCBWYL.cjs +99 -0
- package/dist/chunk-DPXRMSB2.js +130 -0
- package/dist/chunk-DRXPGQM6.cjs +135 -0
- package/dist/chunk-EAU42EVH.js +161 -0
- package/dist/chunk-FC6VDOC7.js +206 -0
- package/dist/chunk-FVO4743A.cjs +134 -0
- package/dist/chunk-G6DV7LX7.cjs +161 -0
- package/dist/chunk-I2RJMDXN.js +90 -0
- package/dist/chunk-IJEEM3DI.js +136 -0
- package/dist/chunk-JBNCMS42.cjs +151 -0
- package/dist/chunk-JZ2SHRGZ.js +87 -0
- package/dist/chunk-KARFFIMP.js +696 -0
- package/dist/chunk-LIQSVJLS.js +177 -0
- package/dist/chunk-LKPXHW5N.cjs +181 -0
- package/dist/chunk-MAQRXYE6.js +118 -0
- package/dist/chunk-MCDESS3T.js +69 -0
- package/dist/chunk-MG25BEV4.cjs +160 -0
- package/dist/chunk-NKCYXBGX.js +99 -0
- package/dist/chunk-OEK7QSQP.js +75 -0
- package/dist/chunk-OMFQ7Z63.cjs +696 -0
- package/dist/chunk-OP4KV3BY.cjs +124 -0
- package/dist/chunk-P2NONIMS.js +257 -0
- package/dist/chunk-P364KRO5.js +61 -0
- package/dist/chunk-PGSDXR2I.js +71 -0
- package/dist/chunk-PL2GERLG.cjs +61 -0
- package/dist/chunk-R5G4V7C6.cjs +75 -0
- package/dist/chunk-RKHX3DGH.js +127 -0
- package/dist/chunk-TSHL7ZO2.js +134 -0
- package/dist/chunk-UFNVCUPQ.cjs +301 -0
- package/dist/chunk-VCRKYMJM.js +301 -0
- package/dist/chunk-VDOAPLA6.cjs +257 -0
- package/dist/chunk-VP5CCP5F.cjs +90 -0
- package/dist/chunk-W2EWMV3A.cjs +87 -0
- package/dist/chunk-WWRFBLCR.cjs +146 -0
- package/dist/chunk-YALLOVNO.cjs +118 -0
- package/dist/chunk-YAU6JCYL.cjs +71 -0
- package/dist/chunk-YWV2BBXN.cjs +2526 -0
- package/dist/chunk-ZBOQCXD4.js +2526 -0
- package/dist/chunk-ZFQQXWNB.js +151 -0
- package/dist/common/boolean.cjs +7 -0
- package/dist/common/boolean.d.cts +119 -0
- package/dist/common/boolean.d.ts +119 -0
- package/dist/common/boolean.js +7 -0
- package/dist/common/color.cjs +9 -0
- package/dist/common/color.d.cts +26 -0
- package/dist/common/color.d.ts +26 -0
- package/dist/common/color.js +9 -0
- package/dist/common/coordinate.cjs +11 -0
- package/dist/common/coordinate.d.cts +23 -0
- package/dist/common/coordinate.d.ts +23 -0
- package/dist/common/coordinate.js +11 -0
- package/dist/common/credit-card.cjs +11 -0
- package/dist/common/credit-card.d.cts +22 -0
- package/dist/common/credit-card.d.ts +22 -0
- package/dist/common/credit-card.js +11 -0
- package/dist/common/date.cjs +7 -0
- package/dist/common/date.d.cts +174 -0
- package/dist/common/date.d.ts +174 -0
- package/dist/common/date.js +7 -0
- package/dist/common/datetime.cjs +15 -0
- package/dist/common/datetime.d.cts +301 -0
- package/dist/common/datetime.d.ts +301 -0
- package/dist/common/datetime.js +15 -0
- package/dist/common/email.cjs +7 -0
- package/dist/common/email.d.cts +149 -0
- package/dist/common/email.d.ts +149 -0
- package/dist/common/email.js +7 -0
- package/dist/common/file.cjs +7 -0
- package/dist/common/file.d.cts +178 -0
- package/dist/common/file.d.ts +178 -0
- package/dist/common/file.js +7 -0
- package/dist/common/id.cjs +13 -0
- package/dist/common/id.d.cts +262 -0
- package/dist/common/id.d.ts +262 -0
- package/dist/common/id.js +13 -0
- package/dist/common/ip.cjs +11 -0
- package/dist/common/ip.d.cts +25 -0
- package/dist/common/ip.d.ts +25 -0
- package/dist/common/ip.js +11 -0
- package/dist/common/number.cjs +7 -0
- package/dist/common/number.d.cts +167 -0
- package/dist/common/number.d.ts +167 -0
- package/dist/common/number.js +7 -0
- package/dist/common/password.cjs +7 -0
- package/dist/common/password.d.cts +192 -0
- package/dist/common/password.d.ts +192 -0
- package/dist/common/password.js +7 -0
- package/dist/common/text.cjs +7 -0
- package/dist/common/text.d.cts +156 -0
- package/dist/common/text.d.ts +156 -0
- package/dist/common/text.js +7 -0
- package/dist/common/time.cjs +15 -0
- package/dist/common/time.d.cts +268 -0
- package/dist/common/time.d.ts +268 -0
- package/dist/common/time.js +15 -0
- package/dist/common/url.cjs +7 -0
- package/dist/common/url.d.cts +196 -0
- package/dist/common/url.d.ts +196 -0
- package/dist/common/url.js +7 -0
- package/dist/config-CABSSvAp.d.cts +5 -0
- package/dist/config-CABSSvAp.d.ts +5 -0
- package/dist/index.cjs +180 -5255
- package/dist/index.d.cts +28 -3150
- package/dist/index.d.ts +28 -3150
- package/dist/index.js +135 -5131
- package/dist/taiwan/bank-account.cjs +11 -0
- package/dist/taiwan/bank-account.d.cts +22 -0
- package/dist/taiwan/bank-account.d.ts +22 -0
- package/dist/taiwan/bank-account.js +11 -0
- package/dist/taiwan/business-id.cjs +9 -0
- package/dist/taiwan/business-id.d.cts +133 -0
- package/dist/taiwan/business-id.d.ts +133 -0
- package/dist/taiwan/business-id.js +9 -0
- package/dist/taiwan/fax.cjs +9 -0
- package/dist/taiwan/fax.d.cts +157 -0
- package/dist/taiwan/fax.d.ts +157 -0
- package/dist/taiwan/fax.js +9 -0
- package/dist/taiwan/invoice.cjs +9 -0
- package/dist/taiwan/invoice.d.cts +17 -0
- package/dist/taiwan/invoice.d.ts +17 -0
- package/dist/taiwan/invoice.js +9 -0
- package/dist/taiwan/license-plate.cjs +9 -0
- package/dist/taiwan/license-plate.d.cts +19 -0
- package/dist/taiwan/license-plate.d.ts +19 -0
- package/dist/taiwan/license-plate.js +9 -0
- package/dist/taiwan/mobile.cjs +9 -0
- package/dist/taiwan/mobile.d.cts +146 -0
- package/dist/taiwan/mobile.d.ts +146 -0
- package/dist/taiwan/mobile.js +9 -0
- package/dist/taiwan/national-id.cjs +15 -0
- package/dist/taiwan/national-id.d.cts +214 -0
- package/dist/taiwan/national-id.d.ts +214 -0
- package/dist/taiwan/national-id.js +15 -0
- package/dist/taiwan/passport.cjs +9 -0
- package/dist/taiwan/passport.d.cts +19 -0
- package/dist/taiwan/passport.d.ts +19 -0
- package/dist/taiwan/passport.js +9 -0
- package/dist/taiwan/postal-code.cjs +17 -0
- package/dist/taiwan/postal-code.d.cts +237 -0
- package/dist/taiwan/postal-code.d.ts +237 -0
- package/dist/taiwan/postal-code.js +17 -0
- package/dist/taiwan/tel.cjs +9 -0
- package/dist/taiwan/tel.d.cts +162 -0
- package/dist/taiwan/tel.d.ts +162 -0
- package/dist/taiwan/tel.js +9 -0
- package/package.json +128 -2
- package/src/i18n/locales/en-GB.json +43 -0
- package/src/i18n/locales/en-US.json +43 -0
- package/src/i18n/locales/id-ID.json +43 -0
- package/src/i18n/locales/ja-JP.json +43 -0
- package/src/i18n/locales/ko-KR.json +43 -0
- package/src/i18n/locales/ms-MY.json +43 -0
- package/src/i18n/locales/th-TH.json +43 -0
- package/src/i18n/locales/vi-VN.json +43 -0
- package/src/i18n/locales/zh-CN.json +43 -0
- package/src/i18n/locales/zh-TW.json +43 -0
- package/src/index.ts +10 -2
- package/src/validators/common/color.ts +192 -0
- package/src/validators/common/coordinate.ts +159 -0
- package/src/validators/common/credit-card.ts +134 -0
- package/src/validators/common/ip.ts +210 -0
- package/src/validators/taiwan/bank-account.ts +176 -0
- package/src/validators/taiwan/invoice.ts +84 -0
- package/src/validators/taiwan/license-plate.ts +110 -0
- package/src/validators/taiwan/passport.ts +103 -0
- package/tests/common/color.test.ts +587 -0
- package/tests/common/coordinate.test.ts +345 -0
- package/tests/common/credit-card.test.ts +378 -0
- package/tests/common/ip.test.ts +419 -0
- package/tests/taiwan/bank-account.test.ts +286 -0
- package/tests/taiwan/invoice.test.ts +227 -0
- package/tests/taiwan/license-plate.test.ts +280 -0
- package/tests/taiwan/passport.test.ts +277 -0
- package/tsup.config.ts +36 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
node-version: [18, 20, 22]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: ${{ matrix.node-version }}
|
|
19
|
+
cache: npm
|
|
20
|
+
- run: npm ci
|
|
21
|
+
- run: npx eslint src/
|
|
22
|
+
- run: npx tsc --noEmit
|
|
23
|
+
- run: npm test -- --run
|
|
24
|
+
- run: npm run build
|
package/CLAUDE.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Project Overview
|
|
4
4
|
|
|
5
|
-
`@hy_ong/zod-kit` is a TypeScript library providing pre-built Zod validation schemas with full i18n support (
|
|
5
|
+
`@hy_ong/zod-kit` is a TypeScript library providing pre-built Zod validation schemas with full i18n support (10 locales). It includes common validators (email, password, text, number, credit card, IP, color, coordinate, etc.) and Taiwan-specific validators (National ID, Business ID, mobile, tel, fax, postal code, invoice, license plate, bank account, passport).
|
|
6
6
|
|
|
7
|
-
- **Version:** 0.
|
|
7
|
+
- **Version:** 0.2.0
|
|
8
8
|
- **License:** MIT
|
|
9
9
|
- **NPM:** `@hy_ong/zod-kit`
|
|
10
10
|
- **Peer dependency:** Zod ^4.3.6
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
## Commands
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
# Run all tests (
|
|
16
|
+
# Run all tests (1050 test cases across 25 files)
|
|
17
17
|
npm test
|
|
18
18
|
|
|
19
19
|
# Run tests once (no watch mode)
|
|
@@ -22,13 +22,16 @@ npm test -- --run
|
|
|
22
22
|
# Run specific test file
|
|
23
23
|
npx vitest run tests/common/email.test.ts
|
|
24
24
|
|
|
25
|
-
# Build (ESM + CJS + .d.ts)
|
|
25
|
+
# Build (ESM + CJS + .d.ts, 26 entry points with code splitting)
|
|
26
26
|
npm run build
|
|
27
|
-
#
|
|
27
|
+
# Uses tsup.config.ts for multi-entry build
|
|
28
28
|
|
|
29
29
|
# Lint
|
|
30
30
|
npx eslint src/
|
|
31
31
|
|
|
32
|
+
# Type check
|
|
33
|
+
npx tsc --noEmit
|
|
34
|
+
|
|
32
35
|
# Publish (runs tests + build automatically via prepublishOnly)
|
|
33
36
|
npm publish --access public
|
|
34
37
|
```
|
|
@@ -42,34 +45,65 @@ src/
|
|
|
42
45
|
├── i18n/
|
|
43
46
|
│ ├── index.ts # Translation function t(key, params)
|
|
44
47
|
│ └── locales/
|
|
45
|
-
│ ├── en.json
|
|
46
|
-
│
|
|
48
|
+
│ ├── en-US.json # English (US)
|
|
49
|
+
│ ├── en-GB.json # English (UK)
|
|
50
|
+
│ ├── zh-TW.json # Traditional Chinese
|
|
51
|
+
│ ├── zh-CN.json # Simplified Chinese
|
|
52
|
+
│ ├── ja-JP.json # Japanese
|
|
53
|
+
│ ├── ko-KR.json # Korean
|
|
54
|
+
│ ├── ms-MY.json # Malay
|
|
55
|
+
│ ├── id-ID.json # Indonesian
|
|
56
|
+
│ ├── th-TH.json # Thai
|
|
57
|
+
│ └── vi-VN.json # Vietnamese
|
|
47
58
|
└── validators/
|
|
48
|
-
├── common/ #
|
|
59
|
+
├── common/ # 15 universal validators
|
|
49
60
|
│ ├── boolean.ts
|
|
61
|
+
│ ├── color.ts # Hex, RGB, HSL with alpha support
|
|
62
|
+
│ ├── coordinate.ts # Latitude, longitude, coordinate pairs
|
|
63
|
+
│ ├── credit-card.ts # Luhn algorithm, card type detection
|
|
50
64
|
│ ├── date.ts
|
|
51
65
|
│ ├── datetime.ts # Uses dayjs for parsing
|
|
52
66
|
│ ├── email.ts
|
|
53
67
|
│ ├── file.ts
|
|
54
68
|
│ ├── id.ts # UUID, nanoid, ObjectId
|
|
69
|
+
│ ├── ip.ts # IPv4, IPv6, CIDR support
|
|
55
70
|
│ ├── number.ts
|
|
56
71
|
│ ├── password.ts
|
|
57
72
|
│ ├── text.ts
|
|
58
73
|
│ ├── time.ts
|
|
59
74
|
│ └── url.ts
|
|
60
|
-
└── taiwan/ #
|
|
75
|
+
└── taiwan/ # 10 Taiwan-specific validators
|
|
76
|
+
├── bank-account.ts # 銀行帳號 (bank code + account number)
|
|
61
77
|
├── business-id.ts # 統一編號 (checksum)
|
|
62
78
|
├── fax.ts
|
|
79
|
+
├── invoice.ts # 統一發票 (2 letters + 8 digits)
|
|
80
|
+
├── license-plate.ts # 車牌號碼 (new + legacy formats)
|
|
63
81
|
├── mobile.ts # 09X-XXXX-XXXX
|
|
64
82
|
├── national-id.ts # 身分證/居留證 (checksum)
|
|
83
|
+
├── passport.ts # 護照號碼 (9 digits, type prefix)
|
|
65
84
|
├── postal-code.ts # 3/5/6-digit with official data
|
|
66
85
|
└── tel.ts # Landline + toll-free (0800/0809)
|
|
67
86
|
|
|
68
87
|
tests/ # Mirrors src/validators/ structure
|
|
69
|
-
├── common/ #
|
|
70
|
-
└── taiwan/ #
|
|
88
|
+
├── common/ # 15 test files
|
|
89
|
+
└── taiwan/ # 10 test files
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Per-Module Imports
|
|
93
|
+
|
|
94
|
+
Users can import individual validators for tree-shaking:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Full import
|
|
98
|
+
import { email, twNationalId } from "@hy_ong/zod-kit"
|
|
99
|
+
|
|
100
|
+
// Per-module import (tree-shakeable)
|
|
101
|
+
import { email } from "@hy_ong/zod-kit/common/email"
|
|
102
|
+
import { twNationalId } from "@hy_ong/zod-kit/taiwan/national-id"
|
|
71
103
|
```
|
|
72
104
|
|
|
105
|
+
All 26 sub-modules are configured in `tsup.config.ts` (entry points) and `package.json` (exports map).
|
|
106
|
+
|
|
73
107
|
## Architecture & Patterns
|
|
74
108
|
|
|
75
109
|
### Validator Function Signature
|
|
@@ -95,7 +129,8 @@ All validators use a two-step approach:
|
|
|
95
129
|
|
|
96
130
|
### i18n System
|
|
97
131
|
|
|
98
|
-
-
|
|
132
|
+
- 10 locales: en-US, en-GB, zh-TW, zh-CN, ja-JP, ko-KR, ms-MY, id-ID, th-TH, vi-VN
|
|
133
|
+
- Locale state is global: `setLocale("en-US")` / `setLocale("zh-TW")`
|
|
99
134
|
- Translation keys are dot-separated: `common.email.invalid`
|
|
100
135
|
- Parameter substitution: `${paramName}` in message templates
|
|
101
136
|
- Each validator supports custom `i18n` overrides in options
|
|
@@ -107,6 +142,10 @@ Taiwan validators implement domain-specific algorithms:
|
|
|
107
142
|
- **Postal Code**: Validates against official Chunghwa Post data (28KB+ of mappings)
|
|
108
143
|
- **Tel/Fax**: Area code + digit length rules per region
|
|
109
144
|
- **Mobile**: Operator prefix validation (090-099)
|
|
145
|
+
- **Invoice**: 2-letter prefix + 8-digit format, auto-strip hyphens, auto-uppercase
|
|
146
|
+
- **License Plate**: New (2012+) and legacy formats for car/motorcycle
|
|
147
|
+
- **Bank Account**: Bank code validation against official list + account number length
|
|
148
|
+
- **Passport**: 9-digit format with type prefix (0=diplomatic, 1=official, 2=ordinary, 3=travel)
|
|
110
149
|
|
|
111
150
|
## Code Style
|
|
112
151
|
|
|
@@ -120,23 +159,26 @@ Taiwan validators implement domain-specific algorithms:
|
|
|
120
159
|
|
|
121
160
|
- Commit messages use **Conventional Commits**: `feat(scope):`, `fix(scope):`, `chore:`, `docs:`
|
|
122
161
|
- Every validator exports both a factory function and relevant type definitions
|
|
123
|
-
- Test files use `beforeEach(() => setLocale("en"))` for consistent locale
|
|
162
|
+
- Test files use `beforeEach(() => setLocale("en-US"))` for consistent locale
|
|
124
163
|
- Test structure: `describe("validatorName(required) features")` → nested `describe` per feature → `it` cases
|
|
125
164
|
- Source files are organized by domain: `common/` for universal, `taiwan/` for locale-specific
|
|
126
|
-
-
|
|
165
|
+
- CI runs on GitHub Actions (Node 18/20/22): lint, type-check, test, build
|
|
127
166
|
|
|
128
167
|
## Build Output
|
|
129
168
|
|
|
130
|
-
`dist/` contains
|
|
131
|
-
- `
|
|
132
|
-
- `
|
|
133
|
-
- `
|
|
134
|
-
- `
|
|
169
|
+
`dist/` contains per-module outputs with code splitting:
|
|
170
|
+
- `{module}.js` — ESM bundle
|
|
171
|
+
- `{module}.cjs` — CommonJS bundle
|
|
172
|
+
- `{module}.d.ts` — TypeScript declarations (ESM)
|
|
173
|
+
- `{module}.d.cts` — TypeScript declarations (CJS)
|
|
174
|
+
- `chunk-*.js` / `chunk-*.cjs` — Shared code chunks
|
|
135
175
|
|
|
136
176
|
## Adding a New Validator
|
|
137
177
|
|
|
138
178
|
1. Create `src/validators/{domain}/{name}.ts` following the generic pattern above
|
|
139
|
-
2. Add i18n keys to
|
|
179
|
+
2. Add i18n keys to all 10 locale files in `src/i18n/locales/`
|
|
140
180
|
3. Export from `src/index.ts`
|
|
141
|
-
4.
|
|
142
|
-
5.
|
|
181
|
+
4. Add entry point to `tsup.config.ts`
|
|
182
|
+
5. Add exports map entry to `package.json`
|
|
183
|
+
6. Create `tests/{domain}/{name}.test.ts` with comprehensive coverage
|
|
184
|
+
7. Test with `npx vitest run tests/{domain}/{name}.test.ts`
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLocale,
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-ZBOQCXD4.js";
|
|
5
|
+
|
|
6
|
+
// src/validators/common/date.ts
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import dayjs from "dayjs";
|
|
9
|
+
import customParseFormat from "dayjs/plugin/customParseFormat";
|
|
10
|
+
import isSameOrAfter from "dayjs/plugin/isSameOrAfter";
|
|
11
|
+
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
|
|
12
|
+
import isToday from "dayjs/plugin/isToday";
|
|
13
|
+
import weekday from "dayjs/plugin/weekday";
|
|
14
|
+
dayjs.extend(isSameOrAfter);
|
|
15
|
+
dayjs.extend(isSameOrBefore);
|
|
16
|
+
dayjs.extend(customParseFormat);
|
|
17
|
+
dayjs.extend(isToday);
|
|
18
|
+
dayjs.extend(weekday);
|
|
19
|
+
function date(required, options) {
|
|
20
|
+
const {
|
|
21
|
+
min,
|
|
22
|
+
max,
|
|
23
|
+
format = "YYYY-MM-DD",
|
|
24
|
+
includes,
|
|
25
|
+
excludes,
|
|
26
|
+
mustBePast,
|
|
27
|
+
mustBeFuture,
|
|
28
|
+
mustBeToday,
|
|
29
|
+
mustNotBeToday,
|
|
30
|
+
weekdaysOnly,
|
|
31
|
+
weekendsOnly,
|
|
32
|
+
transform,
|
|
33
|
+
defaultValue = null,
|
|
34
|
+
i18n
|
|
35
|
+
} = options ?? {};
|
|
36
|
+
const isRequired = required ?? false;
|
|
37
|
+
const actualDefaultValue = defaultValue ?? (isRequired ? "" : null);
|
|
38
|
+
const getMessage = (key, params) => {
|
|
39
|
+
if (i18n) {
|
|
40
|
+
const currentLocale = getLocale();
|
|
41
|
+
const customMessages = i18n[currentLocale];
|
|
42
|
+
if (customMessages && customMessages[key]) {
|
|
43
|
+
const template = customMessages[key];
|
|
44
|
+
return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return t(`common.date.${key}`, params);
|
|
48
|
+
};
|
|
49
|
+
const preprocessFn = (val) => {
|
|
50
|
+
if (val === "" || val === null || val === void 0) {
|
|
51
|
+
return actualDefaultValue;
|
|
52
|
+
}
|
|
53
|
+
let processed = String(val).trim();
|
|
54
|
+
if (transform) {
|
|
55
|
+
processed = transform(processed);
|
|
56
|
+
}
|
|
57
|
+
return processed;
|
|
58
|
+
};
|
|
59
|
+
const baseSchema = isRequired ? z.preprocess(preprocessFn, z.string()) : z.preprocess(preprocessFn, z.string().nullable());
|
|
60
|
+
const schema = baseSchema.superRefine((val, ctx) => {
|
|
61
|
+
if (val === null) return;
|
|
62
|
+
if (isRequired && (val === "" || val === "null" || val === "undefined")) {
|
|
63
|
+
ctx.addIssue({ code: "custom", message: getMessage("required") });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (val !== null && !dayjs(val, format, true).isValid()) {
|
|
67
|
+
ctx.addIssue({ code: "custom", message: getMessage("format", { format }) });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const dateObj = dayjs(val, format);
|
|
71
|
+
if (val !== null && min !== void 0 && !dateObj.isSameOrAfter(dayjs(min, format))) {
|
|
72
|
+
ctx.addIssue({ code: "custom", message: getMessage("min", { min }) });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (val !== null && max !== void 0 && !dateObj.isSameOrBefore(dayjs(max, format))) {
|
|
76
|
+
ctx.addIssue({ code: "custom", message: getMessage("max", { max }) });
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (val !== null && includes !== void 0 && !val.includes(includes)) {
|
|
80
|
+
ctx.addIssue({ code: "custom", message: getMessage("includes", { includes }) });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (val !== null && excludes !== void 0) {
|
|
84
|
+
const excludeList = Array.isArray(excludes) ? excludes : [excludes];
|
|
85
|
+
for (const exclude of excludeList) {
|
|
86
|
+
if (val.includes(exclude)) {
|
|
87
|
+
ctx.addIssue({ code: "custom", message: getMessage("excludes", { excludes: exclude }) });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const today = dayjs().startOf("day");
|
|
93
|
+
const targetDate = dateObj.startOf("day");
|
|
94
|
+
if (val !== null && mustBePast && !targetDate.isBefore(today)) {
|
|
95
|
+
ctx.addIssue({ code: "custom", message: getMessage("past") });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (val !== null && mustBeFuture && !targetDate.isAfter(today)) {
|
|
99
|
+
ctx.addIssue({ code: "custom", message: getMessage("future") });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (val !== null && mustBeToday && !targetDate.isSame(today)) {
|
|
103
|
+
ctx.addIssue({ code: "custom", message: getMessage("today") });
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (val !== null && mustNotBeToday && targetDate.isSame(today)) {
|
|
107
|
+
ctx.addIssue({ code: "custom", message: getMessage("notToday") });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (val !== null && weekdaysOnly && (dateObj.day() === 0 || dateObj.day() === 6)) {
|
|
111
|
+
ctx.addIssue({ code: "custom", message: getMessage("weekday") });
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (val !== null && weekendsOnly && dateObj.day() !== 0 && dateObj.day() !== 6) {
|
|
115
|
+
ctx.addIssue({ code: "custom", message: getMessage("weekend") });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return schema;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export {
|
|
123
|
+
date
|
|
124
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLocale,
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-ZBOQCXD4.js";
|
|
5
|
+
|
|
6
|
+
// src/validators/common/number.ts
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
function number(required, options) {
|
|
9
|
+
const { min, max, defaultValue, type = "both", positive, negative, nonNegative, nonPositive, multipleOf, precision, finite = true, transform, parseCommas = false, i18n } = options ?? {};
|
|
10
|
+
const isRequired = required ?? false;
|
|
11
|
+
const getMessage = (key, params) => {
|
|
12
|
+
if (i18n) {
|
|
13
|
+
const currentLocale = getLocale();
|
|
14
|
+
const customMessages = i18n[currentLocale];
|
|
15
|
+
if (customMessages && customMessages[key]) {
|
|
16
|
+
const template = customMessages[key];
|
|
17
|
+
return template.replace(/\$\{(\w+)}/g, (_, k) => params?.[k] ?? "");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return t(`common.number.${key}`, params);
|
|
21
|
+
};
|
|
22
|
+
const actualDefaultValue = defaultValue ?? null;
|
|
23
|
+
const schema = z.preprocess(
|
|
24
|
+
(val) => {
|
|
25
|
+
if (val === "" || val === void 0 || val === null) {
|
|
26
|
+
return actualDefaultValue;
|
|
27
|
+
}
|
|
28
|
+
if (typeof val === "string") {
|
|
29
|
+
let processedVal = val.trim();
|
|
30
|
+
if (parseCommas) {
|
|
31
|
+
processedVal = processedVal.replace(/,/g, "");
|
|
32
|
+
}
|
|
33
|
+
const parsed = Number(processedVal);
|
|
34
|
+
if (isNaN(parsed)) {
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
if (transform) {
|
|
38
|
+
return transform(parsed);
|
|
39
|
+
}
|
|
40
|
+
return parsed;
|
|
41
|
+
}
|
|
42
|
+
if (typeof val === "number") {
|
|
43
|
+
if (transform && Number.isFinite(val)) {
|
|
44
|
+
return transform(val);
|
|
45
|
+
}
|
|
46
|
+
return val;
|
|
47
|
+
}
|
|
48
|
+
return val;
|
|
49
|
+
},
|
|
50
|
+
z.union([z.number(), z.null(), z.nan(), z.custom((val) => val === Infinity || val === -Infinity)])
|
|
51
|
+
).superRefine((val, ctx) => {
|
|
52
|
+
if (isRequired && val === null) {
|
|
53
|
+
ctx.addIssue({
|
|
54
|
+
code: "custom",
|
|
55
|
+
message: getMessage("required")
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (val === null) return;
|
|
60
|
+
if (isNaN(val)) {
|
|
61
|
+
if (type === "integer") {
|
|
62
|
+
ctx.addIssue({
|
|
63
|
+
code: "custom",
|
|
64
|
+
message: getMessage("integer")
|
|
65
|
+
});
|
|
66
|
+
} else if (type === "float") {
|
|
67
|
+
ctx.addIssue({
|
|
68
|
+
code: "custom",
|
|
69
|
+
message: getMessage("float")
|
|
70
|
+
});
|
|
71
|
+
} else {
|
|
72
|
+
ctx.addIssue({
|
|
73
|
+
code: "custom",
|
|
74
|
+
message: getMessage("invalid")
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (finite && !Number.isFinite(val)) {
|
|
80
|
+
ctx.addIssue({
|
|
81
|
+
code: "custom",
|
|
82
|
+
message: getMessage("finite")
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (type === "integer" && !Number.isInteger(val)) {
|
|
87
|
+
ctx.addIssue({
|
|
88
|
+
code: "custom",
|
|
89
|
+
message: getMessage("integer")
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (type === "float" && Number.isInteger(val)) {
|
|
94
|
+
ctx.addIssue({
|
|
95
|
+
code: "custom",
|
|
96
|
+
message: getMessage("float")
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (positive && val <= 0) {
|
|
101
|
+
ctx.addIssue({
|
|
102
|
+
code: "custom",
|
|
103
|
+
message: getMessage("positive")
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (negative && val >= 0) {
|
|
108
|
+
ctx.addIssue({
|
|
109
|
+
code: "custom",
|
|
110
|
+
message: getMessage("negative")
|
|
111
|
+
});
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (nonNegative && val < 0) {
|
|
115
|
+
ctx.addIssue({
|
|
116
|
+
code: "custom",
|
|
117
|
+
message: getMessage("nonNegative")
|
|
118
|
+
});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (nonPositive && val > 0) {
|
|
122
|
+
ctx.addIssue({
|
|
123
|
+
code: "custom",
|
|
124
|
+
message: getMessage("nonPositive")
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (min !== void 0 && val < min) {
|
|
129
|
+
ctx.addIssue({
|
|
130
|
+
code: "custom",
|
|
131
|
+
message: getMessage("min", { min })
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (max !== void 0 && val > max) {
|
|
136
|
+
ctx.addIssue({
|
|
137
|
+
code: "custom",
|
|
138
|
+
message: getMessage("max", { max })
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (multipleOf !== void 0 && val % multipleOf !== 0) {
|
|
143
|
+
ctx.addIssue({
|
|
144
|
+
code: "custom",
|
|
145
|
+
message: getMessage("multipleOf", { multipleOf })
|
|
146
|
+
});
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (precision !== void 0) {
|
|
150
|
+
const decimalPlaces = (val.toString().split(".")[1] || "").length;
|
|
151
|
+
if (decimalPlaces > precision) {
|
|
152
|
+
ctx.addIssue({
|
|
153
|
+
code: "custom",
|
|
154
|
+
message: getMessage("precision", { precision })
|
|
155
|
+
});
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return schema;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export {
|
|
164
|
+
number
|
|
165
|
+
};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkYWV2BBXNcjs = require('./chunk-YWV2BBXN.cjs');
|
|
5
|
+
|
|
6
|
+
// src/validators/common/id.ts
|
|
7
|
+
var _zod = require('zod');
|
|
8
|
+
var ID_PATTERNS = {
|
|
9
|
+
numeric: /^\d+$/,
|
|
10
|
+
uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
|
11
|
+
objectId: /^[0-9a-f]{24}$/i,
|
|
12
|
+
nanoid: /^[A-Za-z0-9_-]{21}$/,
|
|
13
|
+
snowflake: /^\d{19}$/,
|
|
14
|
+
cuid: /^c[a-z0-9]{24}$/,
|
|
15
|
+
ulid: /^[0-9A-HJKMNP-TV-Z]{26}$/,
|
|
16
|
+
shortid: /^[A-Za-z0-9_-]{7,14}$/
|
|
17
|
+
};
|
|
18
|
+
var detectIdType = (value) => {
|
|
19
|
+
const orderedTypes = [
|
|
20
|
+
["uuid", ID_PATTERNS.uuid],
|
|
21
|
+
["objectId", ID_PATTERNS.objectId],
|
|
22
|
+
["snowflake", ID_PATTERNS.snowflake],
|
|
23
|
+
["cuid", ID_PATTERNS.cuid],
|
|
24
|
+
["ulid", ID_PATTERNS.ulid],
|
|
25
|
+
["nanoid", ID_PATTERNS.nanoid],
|
|
26
|
+
["numeric", ID_PATTERNS.numeric],
|
|
27
|
+
["shortid", ID_PATTERNS.shortid]
|
|
28
|
+
// 放最後,因為最通用
|
|
29
|
+
];
|
|
30
|
+
for (const [type, pattern] of orderedTypes) {
|
|
31
|
+
if (pattern.test(value)) {
|
|
32
|
+
return type;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
};
|
|
37
|
+
var validateIdType = (value, type) => {
|
|
38
|
+
if (type === "auto") {
|
|
39
|
+
return detectIdType(value) !== null;
|
|
40
|
+
}
|
|
41
|
+
const pattern = ID_PATTERNS[type];
|
|
42
|
+
return pattern ? pattern.test(value) : false;
|
|
43
|
+
};
|
|
44
|
+
function id(required, options) {
|
|
45
|
+
const { type = "auto", minLength, maxLength, allowedTypes, customRegex, includes, excludes, startsWith, endsWith, caseSensitive = true, transform, defaultValue, i18n } = _nullishCoalesce(options, () => ( {}));
|
|
46
|
+
const isRequired = _nullishCoalesce(required, () => ( false));
|
|
47
|
+
const isNumericType = type === "numeric";
|
|
48
|
+
const actualDefaultValue = defaultValue !== void 0 ? defaultValue : isRequired ? isNumericType ? NaN : "" : null;
|
|
49
|
+
const getMessage = (key, params) => {
|
|
50
|
+
if (i18n) {
|
|
51
|
+
const currentLocale = _chunkYWV2BBXNcjs.getLocale.call(void 0, );
|
|
52
|
+
const customMessages = i18n[currentLocale];
|
|
53
|
+
if (customMessages && customMessages[key]) {
|
|
54
|
+
const template = customMessages[key];
|
|
55
|
+
return template.replace(/\$\{(\w+)}/g, (_match, k) => _nullishCoalesce(_optionalChain([params, 'optionalAccess', _ => _[k]]), () => ( "")));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return _chunkYWV2BBXNcjs.t.call(void 0, `common.id.${key}`, params);
|
|
59
|
+
};
|
|
60
|
+
const preprocessNumericFn = (val) => {
|
|
61
|
+
if (val === "" || val === null || val === void 0) {
|
|
62
|
+
if (isRequired && defaultValue === void 0) {
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
return actualDefaultValue;
|
|
66
|
+
}
|
|
67
|
+
return Number(val);
|
|
68
|
+
};
|
|
69
|
+
const preprocessStringFn = (val) => {
|
|
70
|
+
if (val === "" || val === null || val === void 0) {
|
|
71
|
+
return actualDefaultValue;
|
|
72
|
+
}
|
|
73
|
+
let processed = String(val);
|
|
74
|
+
if (transform) {
|
|
75
|
+
processed = transform(processed);
|
|
76
|
+
}
|
|
77
|
+
return processed;
|
|
78
|
+
};
|
|
79
|
+
if (isNumericType) {
|
|
80
|
+
const numericSchema = _zod.z.preprocess(preprocessNumericFn, _zod.z.any()).superRefine((val, ctx) => {
|
|
81
|
+
if (!isRequired && val === null) return;
|
|
82
|
+
if (val === void 0 || isRequired && val === null) {
|
|
83
|
+
ctx.addIssue({ code: "custom", message: getMessage("required") });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (typeof val !== "number" || isNaN(val)) {
|
|
87
|
+
ctx.addIssue({ code: "custom", message: getMessage("numeric") });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const strVal = String(val);
|
|
91
|
+
if (!ID_PATTERNS.numeric.test(strVal)) {
|
|
92
|
+
ctx.addIssue({ code: "custom", message: getMessage("numeric") });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (minLength !== void 0 && strVal.length < minLength) {
|
|
96
|
+
ctx.addIssue({ code: "custom", message: getMessage("minLength", { minLength }) });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (maxLength !== void 0 && strVal.length > maxLength) {
|
|
100
|
+
ctx.addIssue({ code: "custom", message: getMessage("maxLength", { maxLength }) });
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
return numericSchema;
|
|
105
|
+
}
|
|
106
|
+
const baseSchema = isRequired ? _zod.z.preprocess(preprocessStringFn, _zod.z.string()) : _zod.z.preprocess(preprocessStringFn, _zod.z.string().nullable());
|
|
107
|
+
const schema = baseSchema.superRefine((val, ctx) => {
|
|
108
|
+
if (val === null) return;
|
|
109
|
+
if (isRequired && (val === "" || val === "null" || val === "undefined")) {
|
|
110
|
+
ctx.addIssue({ code: "custom", message: getMessage("required") });
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const comparisonVal = !caseSensitive ? val.toLowerCase() : val;
|
|
114
|
+
if (val !== null && minLength !== void 0 && val.length < minLength) {
|
|
115
|
+
ctx.addIssue({ code: "custom", message: getMessage("minLength", { minLength }) });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (val !== null && maxLength !== void 0 && val.length > maxLength) {
|
|
119
|
+
ctx.addIssue({ code: "custom", message: getMessage("maxLength", { maxLength }) });
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const hasContentValidations = customRegex !== void 0 || startsWith !== void 0 || endsWith !== void 0 || includes !== void 0 || excludes !== void 0;
|
|
123
|
+
if (val !== null && customRegex !== void 0) {
|
|
124
|
+
if (!customRegex.test(val)) {
|
|
125
|
+
ctx.addIssue({ code: "custom", message: getMessage("customFormat") });
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
} else if (val !== null && !hasContentValidations) {
|
|
129
|
+
let isValidId;
|
|
130
|
+
if (allowedTypes && allowedTypes.length > 0) {
|
|
131
|
+
isValidId = allowedTypes.some((allowedType) => validateIdType(val, allowedType));
|
|
132
|
+
if (!isValidId) {
|
|
133
|
+
const typeNames = allowedTypes.join(", ");
|
|
134
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") + ` (allowed types: ${typeNames})` });
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
} else if (type && type !== "auto") {
|
|
138
|
+
isValidId = validateIdType(val, type);
|
|
139
|
+
if (!isValidId) {
|
|
140
|
+
ctx.addIssue({ code: "custom", message: getMessage(type) || getMessage("invalid") });
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
isValidId = detectIdType(val) !== null;
|
|
145
|
+
if (!isValidId) {
|
|
146
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} else if (val !== null && hasContentValidations && type && type !== "auto" && !customRegex) {
|
|
151
|
+
if (allowedTypes && allowedTypes.length > 0) {
|
|
152
|
+
const isValidType = allowedTypes.some((allowedType) => validateIdType(val, allowedType));
|
|
153
|
+
if (!isValidType) {
|
|
154
|
+
const typeNames = allowedTypes.join(", ");
|
|
155
|
+
ctx.addIssue({ code: "custom", message: getMessage("invalid") + ` (allowed types: ${typeNames})` });
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
if (!validateIdType(val, type)) {
|
|
160
|
+
ctx.addIssue({ code: "custom", message: getMessage(type) || getMessage("invalid") });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const searchStartsWith = !caseSensitive && startsWith ? startsWith.toLowerCase() : startsWith;
|
|
166
|
+
const searchEndsWith = !caseSensitive && endsWith ? endsWith.toLowerCase() : endsWith;
|
|
167
|
+
const searchIncludes = !caseSensitive && includes ? includes.toLowerCase() : includes;
|
|
168
|
+
if (val !== null && startsWith !== void 0 && !comparisonVal.startsWith(searchStartsWith)) {
|
|
169
|
+
ctx.addIssue({ code: "custom", message: getMessage("startsWith", { startsWith }) });
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (val !== null && endsWith !== void 0 && !comparisonVal.endsWith(searchEndsWith)) {
|
|
173
|
+
ctx.addIssue({ code: "custom", message: getMessage("endsWith", { endsWith }) });
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (val !== null && includes !== void 0 && !comparisonVal.includes(searchIncludes)) {
|
|
177
|
+
ctx.addIssue({ code: "custom", message: getMessage("includes", { includes }) });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (val !== null && excludes !== void 0) {
|
|
181
|
+
const excludeList = Array.isArray(excludes) ? excludes : [excludes];
|
|
182
|
+
for (const exclude of excludeList) {
|
|
183
|
+
const searchExclude = !caseSensitive ? exclude.toLowerCase() : exclude;
|
|
184
|
+
if (comparisonVal.includes(searchExclude)) {
|
|
185
|
+
ctx.addIssue({ code: "custom", message: getMessage("excludes", { excludes: exclude }) });
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}).transform((val) => {
|
|
191
|
+
if (val === null) return val;
|
|
192
|
+
const shouldPreserveCase = type === "uuid" || type === "objectId";
|
|
193
|
+
if (!caseSensitive && !shouldPreserveCase) {
|
|
194
|
+
return val.toLowerCase();
|
|
195
|
+
}
|
|
196
|
+
return val;
|
|
197
|
+
});
|
|
198
|
+
return schema;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
exports.ID_PATTERNS = ID_PATTERNS; exports.detectIdType = detectIdType; exports.validateIdType = validateIdType; exports.id = id;
|