schema-dsl 2.0.0 → 2.0.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/CHANGELOG.md +130 -113
- package/LICENSE +21 -21
- package/README.md +628 -628
- package/dist/{DslBuilder-DkLaOo9Q.d.ts → DslBuilder-BIgQOAXp.d.ts} +2 -0
- package/dist/{DslBuilder-DQDN0ZxZ.d.cts → DslBuilder-CjHTucNQ.d.cts} +2 -0
- package/dist/{Validator-hFWKGxir.d.ts → Validator-CllRdrY0.d.ts} +1 -1
- package/dist/{Validator-C7GsVQOH.d.cts → Validator-D6okG9tr.d.cts} +1 -1
- package/dist/index.cjs +75 -29
- package/dist/index.d.cts +10 -4
- package/dist/index.d.ts +10 -4
- package/dist/index.js +75 -29
- package/dist/plugins/custom-format.cjs +33 -17
- package/dist/plugins/custom-format.d.cts +1 -1
- package/dist/plugins/custom-format.d.ts +1 -1
- package/dist/plugins/custom-format.js +33 -17
- package/dist/plugins/custom-type-example.cjs +33 -17
- package/dist/plugins/custom-type-example.d.cts +1 -1
- package/dist/plugins/custom-type-example.d.ts +1 -1
- package/dist/plugins/custom-type-example.js +33 -17
- package/dist/plugins/custom-validator.cjs +0 -2
- package/dist/plugins/custom-validator.d.cts +1 -1
- package/dist/plugins/custom-validator.d.ts +1 -1
- package/dist/plugins/custom-validator.js +0 -2
- package/docs/FEATURE-INDEX.md +553 -553
- package/docs/add-custom-locale.md +496 -496
- package/docs/add-keyword.md +24 -24
- package/docs/api-reference.md +1047 -1047
- package/docs/api.md +13 -13
- package/docs/best-practices-project-structure.md +417 -417
- package/docs/best-practices.md +712 -712
- package/docs/cache-manager.md +344 -344
- package/docs/compile.md +45 -45
- package/docs/conditional-api.md +1307 -1307
- package/docs/custom-extensions-guide.md +339 -339
- package/docs/design-philosophy.md +606 -606
- package/docs/doc-index.md +324 -324
- package/docs/dsl-syntax.md +714 -714
- package/docs/dynamic-locale.md +608 -608
- package/docs/enum.md +482 -482
- package/docs/error-handling.md +1975 -1975
- package/docs/export-guide.md +501 -501
- package/docs/export-limitations.md +567 -567
- package/docs/faq.md +596 -596
- package/docs/frontend-i18n-guide.md +307 -307
- package/docs/i18n-user-guide.md +487 -487
- package/docs/i18n.md +476 -476
- package/docs/index.md +48 -48
- package/docs/json-schema-basics.md +40 -40
- package/docs/label-vs-description.md +271 -271
- package/docs/markdown-exporter.md +406 -406
- package/docs/mongodb-exporter.md +302 -302
- package/docs/multi-language.md +26 -26
- package/docs/multi-type-support.md +322 -322
- package/docs/mysql-exporter.md +280 -280
- package/docs/number-operators.md +449 -449
- package/docs/optional-marker-guide.md +326 -326
- package/docs/performance-guide.md +49 -49
- package/docs/plugin-system.md +381 -381
- package/docs/plugin-type-registration.md +34 -34
- package/docs/postgresql-exporter.md +311 -311
- package/docs/public/favicon.svg +4 -4
- package/docs/quick-start.md +435 -435
- package/docs/runtime-locale-support.md +532 -532
- package/docs/schema-helper.md +345 -345
- package/docs/schema-utils-advanced-issues.md +23 -23
- package/docs/schema-utils-best-practices.md +20 -20
- package/docs/schema-utils-chaining.md +150 -150
- package/docs/schema-utils.md +524 -524
- package/docs/security-checklist.md +20 -20
- package/docs/string-extensions.md +488 -488
- package/docs/troubleshooting.md +486 -486
- package/docs/type-converter.md +310 -310
- package/docs/type-reference.md +242 -242
- package/docs/typescript-guide.md +584 -584
- package/docs/union-type-guide.md +157 -157
- package/docs/union-types.md +284 -284
- package/docs/validate-async.md +491 -491
- package/docs/validate-batch.md +49 -49
- package/docs/validate-dsl-object-support.md +578 -578
- package/docs/validate.md +506 -506
- package/docs/validation-guide.md +502 -502
- package/docs/validator.md +39 -39
- package/package.json +131 -131
- package/plugins/custom-format.cjs +8 -8
- package/plugins/custom-type-example.cjs +8 -8
- package/plugins/custom-validator.cjs +8 -8
- package/src/adapters/DslAdapter.ts +111 -111
- package/src/adapters/index.ts +1 -1
- package/src/config/constants.ts +83 -83
- package/src/config/index.ts +2 -2
- package/src/config/patterns.ts +77 -77
- package/src/core/CacheManager.ts +169 -159
- package/src/core/ConditionalBuilder.ts +382 -382
- package/src/core/ConditionalRuntime.ts +27 -27
- package/src/core/ConditionalValidator.ts +254 -254
- package/src/core/DslBuilder.ts +687 -677
- package/src/core/ErrorCodes.ts +38 -38
- package/src/core/ErrorFormatter.ts +271 -271
- package/src/core/JSONSchemaCore.ts +65 -65
- package/src/core/Locale.ts +187 -187
- package/src/core/MessageTemplate.ts +42 -42
- package/src/core/ObjectDslBuilder.ts +64 -64
- package/src/core/PluginManager.ts +326 -326
- package/src/core/StringExtensions.ts +140 -140
- package/src/core/TemplateEngine.ts +44 -44
- package/src/core/Validator.ts +448 -448
- package/src/errors/I18nError.ts +159 -159
- package/src/errors/ValidationError.ts +105 -105
- package/src/exporters/BaseExporter.ts +60 -60
- package/src/exporters/MarkdownExporter.ts +305 -305
- package/src/exporters/MongoDBExporter.ts +126 -126
- package/src/exporters/MySQLExporter.ts +156 -155
- package/src/exporters/PostgreSQLExporter.ts +222 -222
- package/src/exporters/index.ts +18 -18
- package/src/index.ts +651 -633
- package/src/locales/en-US.ts +160 -160
- package/src/locales/es-ES.ts +160 -160
- package/src/locales/fr-FR.ts +160 -160
- package/src/locales/index.ts +103 -103
- package/src/locales/ja-JP.ts +160 -160
- package/src/locales/types.ts +156 -156
- package/src/locales/zh-CN.ts +160 -160
- package/src/parser/ConstraintParser.ts +101 -101
- package/src/parser/DslParser.ts +470 -470
- package/src/parser/SchemaCompiler.ts +66 -66
- package/src/parser/TypeRegistry.ts +250 -250
- package/src/parser/index.ts +6 -6
- package/src/plugins/custom-format.ts +124 -126
- package/src/plugins/custom-type-example.ts +106 -108
- package/src/plugins/custom-validator.ts +138 -140
- package/src/types/conditional.ts +28 -28
- package/src/types/config.ts +59 -59
- package/src/types/dsl.ts +131 -131
- package/src/types/error.ts +60 -60
- package/src/types/index.ts +17 -17
- package/src/types/infer.ts +127 -127
- package/src/types/plugin.ts +58 -58
- package/src/types/safe-regex.d.ts +9 -9
- package/src/types/schema.ts +66 -66
- package/src/types/validate.ts +71 -71
- package/src/utils/SchemaHelper.ts +196 -196
- package/src/utils/SchemaUtils.ts +365 -346
- package/src/utils/TypeConverter.ts +215 -215
- package/src/utils/index.ts +10 -10
- package/src/validators/CustomKeywords.ts +477 -477
|
@@ -1,126 +1,124 @@
|
|
|
1
|
-
import type { Plugin } from '../types/plugin.js'
|
|
2
|
-
import { DslBuilder } from '../core/DslBuilder.js'
|
|
3
|
-
import type { Validator } from '../core/Validator.js'
|
|
4
|
-
|
|
5
|
-
interface FormatConfig {
|
|
6
|
-
pattern?: RegExp
|
|
7
|
-
validate?: (value: string) => boolean
|
|
8
|
-
schema: Record<string, unknown>
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const FORMATS: Record<string, FormatConfig> = {
|
|
12
|
-
'phone-cn': {
|
|
13
|
-
pattern: /^1[3-9]\d{9}$/,
|
|
14
|
-
schema: { type: 'string', pattern: /^1[3-9]\d{9}$/.source, minLength: 11, maxLength: 11 },
|
|
15
|
-
},
|
|
16
|
-
'postal-code-cn': {
|
|
17
|
-
pattern: /^\d{6}$/,
|
|
18
|
-
schema: { type: 'string', pattern: /^\d{6}$/.source, minLength: 6, maxLength: 6 },
|
|
19
|
-
},
|
|
20
|
-
'ipv4-custom': {
|
|
21
|
-
pattern: /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
|
|
22
|
-
schema: { type: 'string', format: 'ipv4' },
|
|
23
|
-
},
|
|
24
|
-
'wechat': {
|
|
25
|
-
pattern: /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/,
|
|
26
|
-
schema: { type: 'string', pattern: /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/.source, minLength: 6, maxLength: 20 },
|
|
27
|
-
},
|
|
28
|
-
'qq': {
|
|
29
|
-
pattern: /^[1-9][0-9]{4,10}$/,
|
|
30
|
-
schema: { type: 'string', pattern: /^[1-9][0-9]{4,10}$/.source, minLength: 5, maxLength: 11 },
|
|
31
|
-
},
|
|
32
|
-
'bank-card': {
|
|
33
|
-
validate: (value: string) => {
|
|
34
|
-
if (!/^\d{16,19}$/.test(value)) return false
|
|
35
|
-
|
|
36
|
-
let sum = 0
|
|
37
|
-
let shouldDouble = false
|
|
38
|
-
|
|
39
|
-
for (let i = value.length - 1; i >= 0; i -= 1) {
|
|
40
|
-
let digit = Number.parseInt(value[i], 10)
|
|
41
|
-
|
|
42
|
-
if (shouldDouble) {
|
|
43
|
-
digit *= 2
|
|
44
|
-
if (digit > 9) digit -= 9
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
sum += digit
|
|
48
|
-
shouldDouble = !shouldDouble
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return sum % 10 === 0
|
|
52
|
-
},
|
|
53
|
-
schema: { type: 'string', minLength: 16, maxLength: 19, pattern: /^\d{16,19}$/.source },
|
|
54
|
-
},
|
|
55
|
-
'license-plate': {
|
|
56
|
-
pattern: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/,
|
|
57
|
-
schema: {
|
|
58
|
-
type: 'string',
|
|
59
|
-
pattern: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/.source,
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
'credit-code': {
|
|
63
|
-
pattern: /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/,
|
|
64
|
-
schema: {
|
|
65
|
-
type: 'string',
|
|
66
|
-
pattern: /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/.source,
|
|
67
|
-
minLength: 18,
|
|
68
|
-
maxLength: 18,
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
'passport-cn': {
|
|
72
|
-
pattern: /^[EG]\d{8}$/,
|
|
73
|
-
schema: { type: 'string', pattern: /^[EG]\d{8}$/.source, minLength: 9, maxLength: 9 },
|
|
74
|
-
},
|
|
75
|
-
'hk-macao-pass': {
|
|
76
|
-
pattern: /^[HM]\d{8,10}$/,
|
|
77
|
-
schema: { type: 'string', pattern: /^[HM]\d{8,10}$/.source, minLength: 9, maxLength: 11 },
|
|
78
|
-
},
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function getAjvLike(core: unknown): {
|
|
82
|
-
addFormat: (name: string, definition: RegExp | { validate: RegExp | ((value: string) => boolean) }) => void
|
|
83
|
-
} {
|
|
84
|
-
const coreRecord = core as { getDefaultValidator?: () => Validator }
|
|
85
|
-
const validator = coreRecord.getDefaultValidator?.()
|
|
86
|
-
if (!validator) {
|
|
87
|
-
throw new Error('getDefaultValidator() is not available. Please provide schema-dsl core object.')
|
|
88
|
-
}
|
|
89
|
-
return validator.getAjv() as {
|
|
90
|
-
addFormat: (name: string, definition: RegExp | { validate: RegExp | ((value: string) => boolean) }) => void
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function getDslBuilderLike(core: unknown): typeof DslBuilder {
|
|
95
|
-
const coreRecord = core as { DslBuilder?: typeof DslBuilder }
|
|
96
|
-
return coreRecord.DslBuilder ?? DslBuilder
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export const customFormatPlugin: Plugin & {
|
|
100
|
-
addCustomFormats: (ajv: { addFormat: (name: string, definition: { validate: RegExp | ((value: string) => boolean) }) => void }, dslBuilder: typeof DslBuilder) => void
|
|
101
|
-
} = {
|
|
102
|
-
name: 'custom-format',
|
|
103
|
-
version: '2.0.0',
|
|
104
|
-
description: 'Custom format validation plugin (with DSL type registration)',
|
|
105
|
-
install(core, _options = {}, _context) {
|
|
106
|
-
const ajv = getAjvLike(core)
|
|
107
|
-
const dslBuilder = getDslBuilderLike(core)
|
|
108
|
-
this.addCustomFormats(ajv, dslBuilder)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
1
|
+
import type { Plugin } from '../types/plugin.js'
|
|
2
|
+
import { DslBuilder } from '../core/DslBuilder.js'
|
|
3
|
+
import type { Validator } from '../core/Validator.js'
|
|
4
|
+
|
|
5
|
+
interface FormatConfig {
|
|
6
|
+
pattern?: RegExp
|
|
7
|
+
validate?: (value: string) => boolean
|
|
8
|
+
schema: Record<string, unknown>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const FORMATS: Record<string, FormatConfig> = {
|
|
12
|
+
'phone-cn': {
|
|
13
|
+
pattern: /^1[3-9]\d{9}$/,
|
|
14
|
+
schema: { type: 'string', pattern: /^1[3-9]\d{9}$/.source, minLength: 11, maxLength: 11 },
|
|
15
|
+
},
|
|
16
|
+
'postal-code-cn': {
|
|
17
|
+
pattern: /^\d{6}$/,
|
|
18
|
+
schema: { type: 'string', pattern: /^\d{6}$/.source, minLength: 6, maxLength: 6 },
|
|
19
|
+
},
|
|
20
|
+
'ipv4-custom': {
|
|
21
|
+
pattern: /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
|
|
22
|
+
schema: { type: 'string', format: 'ipv4' },
|
|
23
|
+
},
|
|
24
|
+
'wechat': {
|
|
25
|
+
pattern: /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/,
|
|
26
|
+
schema: { type: 'string', pattern: /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/.source, minLength: 6, maxLength: 20 },
|
|
27
|
+
},
|
|
28
|
+
'qq': {
|
|
29
|
+
pattern: /^[1-9][0-9]{4,10}$/,
|
|
30
|
+
schema: { type: 'string', pattern: /^[1-9][0-9]{4,10}$/.source, minLength: 5, maxLength: 11 },
|
|
31
|
+
},
|
|
32
|
+
'bank-card': {
|
|
33
|
+
validate: (value: string) => {
|
|
34
|
+
if (!/^\d{16,19}$/.test(value)) return false
|
|
35
|
+
|
|
36
|
+
let sum = 0
|
|
37
|
+
let shouldDouble = false
|
|
38
|
+
|
|
39
|
+
for (let i = value.length - 1; i >= 0; i -= 1) {
|
|
40
|
+
let digit = Number.parseInt(value[i], 10)
|
|
41
|
+
|
|
42
|
+
if (shouldDouble) {
|
|
43
|
+
digit *= 2
|
|
44
|
+
if (digit > 9) digit -= 9
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
sum += digit
|
|
48
|
+
shouldDouble = !shouldDouble
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return sum % 10 === 0
|
|
52
|
+
},
|
|
53
|
+
schema: { type: 'string', minLength: 16, maxLength: 19, pattern: /^\d{16,19}$/.source },
|
|
54
|
+
},
|
|
55
|
+
'license-plate': {
|
|
56
|
+
pattern: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/,
|
|
57
|
+
schema: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
pattern: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/.source,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
'credit-code': {
|
|
63
|
+
pattern: /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/,
|
|
64
|
+
schema: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
pattern: /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/.source,
|
|
67
|
+
minLength: 18,
|
|
68
|
+
maxLength: 18,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
'passport-cn': {
|
|
72
|
+
pattern: /^[EG]\d{8}$/,
|
|
73
|
+
schema: { type: 'string', pattern: /^[EG]\d{8}$/.source, minLength: 9, maxLength: 9 },
|
|
74
|
+
},
|
|
75
|
+
'hk-macao-pass': {
|
|
76
|
+
pattern: /^[HM]\d{8,10}$/,
|
|
77
|
+
schema: { type: 'string', pattern: /^[HM]\d{8,10}$/.source, minLength: 9, maxLength: 11 },
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getAjvLike(core: unknown): {
|
|
82
|
+
addFormat: (name: string, definition: RegExp | { validate: RegExp | ((value: string) => boolean) }) => void
|
|
83
|
+
} {
|
|
84
|
+
const coreRecord = core as { getDefaultValidator?: () => Validator }
|
|
85
|
+
const validator = coreRecord.getDefaultValidator?.()
|
|
86
|
+
if (!validator) {
|
|
87
|
+
throw new Error('getDefaultValidator() is not available. Please provide schema-dsl core object.')
|
|
88
|
+
}
|
|
89
|
+
return validator.getAjv() as {
|
|
90
|
+
addFormat: (name: string, definition: RegExp | { validate: RegExp | ((value: string) => boolean) }) => void
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function getDslBuilderLike(core: unknown): typeof DslBuilder {
|
|
95
|
+
const coreRecord = core as { DslBuilder?: typeof DslBuilder }
|
|
96
|
+
return coreRecord.DslBuilder ?? DslBuilder
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const customFormatPlugin: Plugin & {
|
|
100
|
+
addCustomFormats: (ajv: { addFormat: (name: string, definition: { validate: RegExp | ((value: string) => boolean) }) => void }, dslBuilder: typeof DslBuilder) => void
|
|
101
|
+
} = {
|
|
102
|
+
name: 'custom-format',
|
|
103
|
+
version: '2.0.0',
|
|
104
|
+
description: 'Custom format validation plugin (with DSL type registration)',
|
|
105
|
+
install(core, _options = {}, _context) {
|
|
106
|
+
const ajv = getAjvLike(core)
|
|
107
|
+
const dslBuilder = getDslBuilderLike(core)
|
|
108
|
+
this.addCustomFormats(ajv, dslBuilder)
|
|
109
|
+
},
|
|
110
|
+
uninstall() {
|
|
111
|
+
},
|
|
112
|
+
addCustomFormats(ajv, dslBuilder) {
|
|
113
|
+
for (const [name, config] of Object.entries(FORMATS)) {
|
|
114
|
+
ajv.addFormat(name, {
|
|
115
|
+
validate: config.validate ?? config.pattern!,
|
|
116
|
+
})
|
|
117
|
+
dslBuilder.registerType(name, config.schema)
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default customFormatPlugin
|
|
123
|
+
|
|
124
|
+
|
|
@@ -1,108 +1,106 @@
|
|
|
1
|
-
import type { Plugin } from '../types/plugin.js'
|
|
2
|
-
import { DslBuilder } from '../core/DslBuilder.js'
|
|
3
|
-
|
|
4
|
-
export const customTypeExamplePlugin: Plugin & {
|
|
5
|
-
registerCustomTypes: (dslBuilder: typeof DslBuilder) => void
|
|
6
|
-
} = {
|
|
7
|
-
name: 'custom-type-example',
|
|
8
|
-
version: '1.0.0',
|
|
9
|
-
description: 'Custom type registration example plugin',
|
|
10
|
-
install(core, _options = {}, _context) {
|
|
11
|
-
const coreRecord = core as { DslBuilder?: typeof DslBuilder }
|
|
12
|
-
const builder = coreRecord.DslBuilder ?? DslBuilder
|
|
13
|
-
|
|
14
|
-
if (!builder || typeof builder.registerType !== 'function') {
|
|
15
|
-
throw new Error('DslBuilder.registerType is not available. Please upgrade to schema-dsl v1.1.0+')
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
this.registerCustomTypes(builder)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
{ type: 'string', pattern:
|
|
68
|
-
{ type: 'string', pattern:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
export default customTypeExamplePlugin
|
|
108
|
-
|
|
1
|
+
import type { Plugin } from '../types/plugin.js'
|
|
2
|
+
import { DslBuilder } from '../core/DslBuilder.js'
|
|
3
|
+
|
|
4
|
+
export const customTypeExamplePlugin: Plugin & {
|
|
5
|
+
registerCustomTypes: (dslBuilder: typeof DslBuilder) => void
|
|
6
|
+
} = {
|
|
7
|
+
name: 'custom-type-example',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
description: 'Custom type registration example plugin',
|
|
10
|
+
install(core, _options = {}, _context) {
|
|
11
|
+
const coreRecord = core as { DslBuilder?: typeof DslBuilder }
|
|
12
|
+
const builder = coreRecord.DslBuilder ?? DslBuilder
|
|
13
|
+
|
|
14
|
+
if (!builder || typeof builder.registerType !== 'function') {
|
|
15
|
+
throw new Error('DslBuilder.registerType is not available. Please upgrade to schema-dsl v1.1.0+')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
this.registerCustomTypes(builder)
|
|
19
|
+
},
|
|
20
|
+
uninstall() {
|
|
21
|
+
},
|
|
22
|
+
registerCustomTypes(dslBuilder) {
|
|
23
|
+
dslBuilder.registerType('order-id', {
|
|
24
|
+
type: 'string',
|
|
25
|
+
pattern: /^ORD[0-9]{12}$/.source,
|
|
26
|
+
minLength: 15,
|
|
27
|
+
maxLength: 15,
|
|
28
|
+
_customMessages: {
|
|
29
|
+
pattern: 'Invalid order ID format; must be 15 characters starting with ORD',
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
dslBuilder.registerType('sku', {
|
|
34
|
+
type: 'string',
|
|
35
|
+
pattern: /^SKU-[A-Z0-9]{6,10}$/.source,
|
|
36
|
+
minLength: 10,
|
|
37
|
+
maxLength: 14,
|
|
38
|
+
_customMessages: {
|
|
39
|
+
pattern: 'Invalid SKU format; must be SKU- followed by 6–10 alphanumeric characters',
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
dslBuilder.registerType('price', {
|
|
44
|
+
type: 'number',
|
|
45
|
+
minimum: 0,
|
|
46
|
+
multipleOf: 0.01,
|
|
47
|
+
_customMessages: {
|
|
48
|
+
minimum: 'Price cannot be negative',
|
|
49
|
+
multipleOf: 'Price can have at most 2 decimal places',
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
dslBuilder.registerType('rating', {
|
|
54
|
+
type: 'integer',
|
|
55
|
+
minimum: 1,
|
|
56
|
+
maximum: 5,
|
|
57
|
+
_customMessages: {
|
|
58
|
+
minimum: 'Rating cannot be lower than 1 star',
|
|
59
|
+
maximum: 'Rating cannot exceed 5 stars',
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
dslBuilder.registerType('color-code', {
|
|
64
|
+
oneOf: [
|
|
65
|
+
{ type: 'string', pattern: /^#[0-9A-Fa-f]{6}$/.source },
|
|
66
|
+
{ type: 'string', pattern: /^#[0-9A-Fa-f]{3}$/.source },
|
|
67
|
+
{ type: 'string', pattern: /^rgb\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\)$/.source },
|
|
68
|
+
{ type: 'string', pattern: /^rgba\(\d{1,3},\s*\d{1,3},\s*\d{1,3},\s*(0|1|0?\.\d+)\)$/.source },
|
|
69
|
+
],
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
dslBuilder.registerType('semver', {
|
|
73
|
+
type: 'string',
|
|
74
|
+
pattern: /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.source,
|
|
75
|
+
_customMessages: {
|
|
76
|
+
pattern: 'Invalid version format; must follow semantic versioning (e.g. 1.0.0, 2.1.3-beta.1)',
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
dslBuilder.registerType('dynamic-age', () => {
|
|
81
|
+
const currentYear = new Date().getFullYear()
|
|
82
|
+
return {
|
|
83
|
+
type: 'integer',
|
|
84
|
+
minimum: 0,
|
|
85
|
+
maximum: currentYear - 1900,
|
|
86
|
+
_customMessages: {
|
|
87
|
+
minimum: 'Age cannot be negative',
|
|
88
|
+
maximum: `Age cannot exceed ${currentYear - 1900} years`,
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
dslBuilder.registerType('phone-intl', {
|
|
94
|
+
type: 'string',
|
|
95
|
+
pattern: /^\+?[1-9]\d{1,14}$/.source,
|
|
96
|
+
minLength: 8,
|
|
97
|
+
maxLength: 15,
|
|
98
|
+
_customMessages: {
|
|
99
|
+
pattern: 'Please enter a valid international phone number (E.164 format)',
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export default customTypeExamplePlugin
|
|
106
|
+
|