schema-dsl 1.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 (116) hide show
  1. package/.eslintignore +10 -0
  2. package/.eslintrc.json +27 -0
  3. package/.github/CODE_OF_CONDUCT.md +45 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +57 -0
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -0
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +45 -0
  7. package/.github/ISSUE_TEMPLATE/question.md +31 -0
  8. package/.github/PULL_REQUEST_TEMPLATE.md +70 -0
  9. package/.github/SECURITY.md +184 -0
  10. package/.github/workflows/ci.yml +33 -0
  11. package/CHANGELOG.md +633 -0
  12. package/CONTRIBUTING.md +368 -0
  13. package/LICENSE +21 -0
  14. package/README.md +1184 -0
  15. package/STATUS.md +101 -0
  16. package/docs/FEATURE-INDEX.md +519 -0
  17. package/docs/INDEX.md +253 -0
  18. package/docs/api-reference.md +1096 -0
  19. package/docs/best-practices.md +672 -0
  20. package/docs/cache-manager.md +336 -0
  21. package/docs/design-philosophy.md +601 -0
  22. package/docs/dsl-syntax.md +653 -0
  23. package/docs/dynamic-locale.md +552 -0
  24. package/docs/error-handling.md +703 -0
  25. package/docs/export-guide.md +462 -0
  26. package/docs/export-limitations.md +551 -0
  27. package/docs/faq.md +577 -0
  28. package/docs/frontend-i18n-guide.md +290 -0
  29. package/docs/i18n-user-guide.md +476 -0
  30. package/docs/label-vs-description.md +262 -0
  31. package/docs/markdown-exporter.md +397 -0
  32. package/docs/mongodb-exporter.md +295 -0
  33. package/docs/multi-type-support.md +319 -0
  34. package/docs/mysql-exporter.md +273 -0
  35. package/docs/plugin-system.md +542 -0
  36. package/docs/postgresql-exporter.md +304 -0
  37. package/docs/quick-start.md +761 -0
  38. package/docs/schema-helper.md +340 -0
  39. package/docs/schema-utils-chaining.md +143 -0
  40. package/docs/schema-utils.md +490 -0
  41. package/docs/string-extensions.md +480 -0
  42. package/docs/troubleshooting.md +471 -0
  43. package/docs/type-converter.md +319 -0
  44. package/docs/type-reference.md +219 -0
  45. package/docs/validate-async.md +480 -0
  46. package/docs/validate.md +486 -0
  47. package/docs/validation-guide.md +484 -0
  48. package/examples/array-dsl-example.js +227 -0
  49. package/examples/custom-extension.js +85 -0
  50. package/examples/dsl-match-example.js +74 -0
  51. package/examples/dsl-style.js +118 -0
  52. package/examples/dynamic-locale-configuration.js +348 -0
  53. package/examples/dynamic-locale-example.js +287 -0
  54. package/examples/export-demo.js +130 -0
  55. package/examples/express-integration.js +376 -0
  56. package/examples/i18n-full-demo.js +310 -0
  57. package/examples/i18n-memory-safety.examples.js +268 -0
  58. package/examples/markdown-export.js +71 -0
  59. package/examples/middleware-usage.js +93 -0
  60. package/examples/new-features-comparison.js +315 -0
  61. package/examples/password-reset/README.md +153 -0
  62. package/examples/password-reset/schema.js +26 -0
  63. package/examples/password-reset/test.js +101 -0
  64. package/examples/plugin-system.examples.js +205 -0
  65. package/examples/schema-utils-chaining.examples.js +250 -0
  66. package/examples/simple-example.js +122 -0
  67. package/examples/string-extensions.js +297 -0
  68. package/examples/user-registration/README.md +156 -0
  69. package/examples/user-registration/routes.js +92 -0
  70. package/examples/user-registration/schema.js +150 -0
  71. package/examples/user-registration/server.js +74 -0
  72. package/index.d.ts +1999 -0
  73. package/index.js +282 -0
  74. package/index.mjs +30 -0
  75. package/lib/adapters/DslAdapter.js +699 -0
  76. package/lib/adapters/index.js +20 -0
  77. package/lib/config/constants.js +286 -0
  78. package/lib/config/patterns/creditCard.js +9 -0
  79. package/lib/config/patterns/idCard.js +9 -0
  80. package/lib/config/patterns/index.js +8 -0
  81. package/lib/config/patterns/licensePlate.js +4 -0
  82. package/lib/config/patterns/passport.js +4 -0
  83. package/lib/config/patterns/phone.js +9 -0
  84. package/lib/config/patterns/postalCode.js +5 -0
  85. package/lib/core/CacheManager.js +376 -0
  86. package/lib/core/DslBuilder.js +740 -0
  87. package/lib/core/ErrorCodes.js +233 -0
  88. package/lib/core/ErrorFormatter.js +342 -0
  89. package/lib/core/JSONSchemaCore.js +347 -0
  90. package/lib/core/Locale.js +119 -0
  91. package/lib/core/MessageTemplate.js +89 -0
  92. package/lib/core/PluginManager.js +448 -0
  93. package/lib/core/StringExtensions.js +209 -0
  94. package/lib/core/Validator.js +376 -0
  95. package/lib/errors/ValidationError.js +191 -0
  96. package/lib/exporters/MarkdownExporter.js +420 -0
  97. package/lib/exporters/MongoDBExporter.js +162 -0
  98. package/lib/exporters/MySQLExporter.js +212 -0
  99. package/lib/exporters/PostgreSQLExporter.js +289 -0
  100. package/lib/exporters/index.js +24 -0
  101. package/lib/locales/en-US.js +65 -0
  102. package/lib/locales/es-ES.js +66 -0
  103. package/lib/locales/fr-FR.js +66 -0
  104. package/lib/locales/index.js +8 -0
  105. package/lib/locales/ja-JP.js +66 -0
  106. package/lib/locales/zh-CN.js +93 -0
  107. package/lib/utils/LRUCache.js +174 -0
  108. package/lib/utils/SchemaHelper.js +240 -0
  109. package/lib/utils/SchemaUtils.js +445 -0
  110. package/lib/utils/TypeConverter.js +245 -0
  111. package/lib/utils/index.js +13 -0
  112. package/lib/validators/CustomKeywords.js +203 -0
  113. package/lib/validators/index.js +11 -0
  114. package/package.json +70 -0
  115. package/plugins/custom-format.js +101 -0
  116. package/plugins/custom-validator.js +200 -0
@@ -0,0 +1,212 @@
1
+ /**
2
+ * MySQL DDL导出器
3
+ *
4
+ * 将JSON Schema转换为MySQL CREATE TABLE语句
5
+ *
6
+ * @module lib/exporters/MySQLExporter
7
+ * @version 1.0.0
8
+ */
9
+
10
+ const TypeConverter = require('../utils/TypeConverter');
11
+ const SchemaHelper = require('../utils/SchemaHelper');
12
+
13
+ /**
14
+ * MySQL导出器类
15
+ * @class MySQLExporter
16
+ */
17
+ class MySQLExporter {
18
+ /**
19
+ * 构造函数
20
+ * @param {Object} options - 配置选项
21
+ * @param {string} options.engine - 存储引擎(默认InnoDB)
22
+ * @param {string} options.charset - 字符集(默认utf8mb4)
23
+ * @param {string} options.collate - 排序规则(默认utf8mb4_unicode_ci)
24
+ */
25
+ constructor(options = {}) {
26
+ this.options = {
27
+ engine: options.engine || 'InnoDB',
28
+ charset: options.charset || 'utf8mb4',
29
+ collate: options.collate || 'utf8mb4_unicode_ci',
30
+ ...options
31
+ };
32
+ }
33
+
34
+ /**
35
+ * 导出为MySQL CREATE TABLE语句
36
+ * @param {string} tableName - 表名
37
+ * @param {Object} jsonSchema - JSON Schema对象
38
+ * @returns {string} MySQL DDL语句
39
+ */
40
+ export(tableName, jsonSchema) {
41
+ if (!tableName || typeof tableName !== 'string') {
42
+ throw new Error('Table name is required');
43
+ }
44
+ if (!jsonSchema || jsonSchema.type !== 'object') {
45
+ throw new Error('JSON Schema must be an object type');
46
+ }
47
+
48
+ const columns = this._convertProperties(jsonSchema);
49
+ const primaryKey = this._detectPrimaryKey(jsonSchema);
50
+
51
+ let ddl = `CREATE TABLE \`${tableName}\` (\n`;
52
+
53
+ // 添加列定义
54
+ const columnDefs = columns.map(col => ` ${col}`).join(',\n');
55
+ ddl += columnDefs;
56
+
57
+ // 添加主键
58
+ if (primaryKey) {
59
+ ddl += `,\n PRIMARY KEY (\`${primaryKey}\`)`;
60
+ }
61
+
62
+ ddl += `\n)`;
63
+
64
+ // 添加表选项
65
+ ddl += ` ENGINE=${this.options.engine}`;
66
+ ddl += ` DEFAULT CHARSET=${this.options.charset}`;
67
+ ddl += ` COLLATE=${this.options.collate};`;
68
+
69
+ return ddl;
70
+ }
71
+
72
+ /**
73
+ * 转换properties为列定义
74
+ * @private
75
+ * @param {Object} schema - JSON Schema对象
76
+ * @returns {Array<string>} 列定义数组
77
+ */
78
+ _convertProperties(schema) {
79
+ if (!schema.properties) {
80
+ return [];
81
+ }
82
+
83
+ const columns = [];
84
+ const required = schema.required || [];
85
+
86
+ for (const [name, propSchema] of Object.entries(schema.properties)) {
87
+ const columnDef = this._convertColumn(name, propSchema, required.includes(name));
88
+ columns.push(columnDef);
89
+ }
90
+
91
+ return columns;
92
+ }
93
+
94
+ /**
95
+ * 转换单个列
96
+ * @private
97
+ * @param {string} name - 列名
98
+ * @param {Object} schema - 属性Schema
99
+ * @param {boolean} isRequired - 是否必填
100
+ * @returns {string} 列定义字符串
101
+ */
102
+ _convertColumn(name, schema, isRequired) {
103
+ const constraints = TypeConverter.extractConstraints(schema);
104
+ const mysqlType = TypeConverter.toMySQLType(schema.type, constraints);
105
+
106
+ let def = `\`${name}\` ${mysqlType}`;
107
+
108
+ // NULL约束
109
+ if (isRequired) {
110
+ def += ' NOT NULL';
111
+ } else {
112
+ def += ' NULL';
113
+ }
114
+
115
+ // 默认值
116
+ if (schema.default !== undefined) {
117
+ const defaultValue = this._formatDefaultValue(schema.default, schema.type);
118
+ def += ` DEFAULT ${defaultValue}`;
119
+ }
120
+
121
+ // 注释
122
+ if (schema.description) {
123
+ def += ` COMMENT '${this._escapeString(schema.description)}'`;
124
+ }
125
+
126
+ return def;
127
+ }
128
+
129
+ /**
130
+ * 格式化默认值
131
+ * @private
132
+ * @param {*} value - 默认值
133
+ * @param {string} type - 类型
134
+ * @returns {string} 格式化后的默认值
135
+ */
136
+ _formatDefaultValue(value, type) {
137
+ if (value === null) {
138
+ return 'NULL';
139
+ }
140
+
141
+ if (type === 'string') {
142
+ return `'${this._escapeString(value)}'`;
143
+ }
144
+
145
+ if (type === 'boolean') {
146
+ return value ? '1' : '0';
147
+ }
148
+
149
+ return value.toString();
150
+ }
151
+
152
+ /**
153
+ * 转义字符串
154
+ * @private
155
+ * @param {string} str - 字符串
156
+ * @returns {string} 转义后的字符串
157
+ */
158
+ _escapeString(str) {
159
+ return str.replace(/'/g, "''");
160
+ }
161
+
162
+ /**
163
+ * 检测主键
164
+ * @private
165
+ * @param {Object} schema - JSON Schema对象
166
+ * @returns {string|null} 主键列名
167
+ */
168
+ _detectPrimaryKey(schema) {
169
+ if (!schema.properties) {
170
+ return null;
171
+ }
172
+
173
+ // 查找名为id或_id的字段
174
+ if (schema.properties.id) {
175
+ return 'id';
176
+ }
177
+ if (schema.properties._id) {
178
+ return '_id';
179
+ }
180
+
181
+ return null;
182
+ }
183
+
184
+ /**
185
+ * 生成索引DDL
186
+ * @param {string} tableName - 表名
187
+ * @param {string} columnName - 列名
188
+ * @param {Object} options - 索引选项
189
+ * @returns {string} CREATE INDEX语句
190
+ */
191
+ generateIndex(tableName, columnName, options = {}) {
192
+ const indexName = options.name || `idx_${tableName}_${columnName}`;
193
+ const unique = options.unique ? 'UNIQUE ' : '';
194
+
195
+ return `CREATE ${unique}INDEX \`${indexName}\` ON \`${tableName}\` (\`${columnName}\`);`;
196
+ }
197
+
198
+ /**
199
+ * 静态方法:快速导出
200
+ * @static
201
+ * @param {string} tableName - 表名
202
+ * @param {Object} jsonSchema - JSON Schema对象
203
+ * @returns {string} MySQL DDL语句
204
+ */
205
+ static export(tableName, jsonSchema) {
206
+ const exporter = new MySQLExporter();
207
+ return exporter.export(tableName, jsonSchema);
208
+ }
209
+ }
210
+
211
+ module.exports = MySQLExporter;
212
+
@@ -0,0 +1,289 @@
1
+ /**
2
+ * PostgreSQL DDL导出器
3
+ *
4
+ * 将JSON Schema转换为PostgreSQL CREATE TABLE语句
5
+ *
6
+ * @module lib/exporters/PostgreSQLExporter
7
+ * @version 1.0.0
8
+ */
9
+
10
+ const TypeConverter = require('../utils/TypeConverter');
11
+
12
+ /**
13
+ * PostgreSQL导出器类
14
+ * @class PostgreSQLExporter
15
+ */
16
+ class PostgreSQLExporter {
17
+ /**
18
+ * 构造函数
19
+ * @param {Object} options - 配置选项
20
+ * @param {string} options.schema - PostgreSQL schema名称(默认public)
21
+ */
22
+ constructor(options = {}) {
23
+ this.options = {
24
+ schema: options.schema || 'public',
25
+ ...options
26
+ };
27
+ }
28
+
29
+ /**
30
+ * 导出为PostgreSQL CREATE TABLE语句
31
+ * @param {string} tableName - 表名
32
+ * @param {Object} jsonSchema - JSON Schema对象
33
+ * @returns {string} PostgreSQL DDL语句
34
+ */
35
+ export(tableName, jsonSchema) {
36
+ if (!tableName || typeof tableName !== 'string') {
37
+ throw new Error('Table name is required');
38
+ }
39
+ if (!jsonSchema || jsonSchema.type !== 'object') {
40
+ throw new Error('JSON Schema must be an object type');
41
+ }
42
+
43
+ const fullTableName = `${this.options.schema}.${tableName}`;
44
+ const columns = this._convertProperties(jsonSchema);
45
+ const primaryKey = this._detectPrimaryKey(jsonSchema);
46
+
47
+ let ddl = `CREATE TABLE ${fullTableName} (\n`;
48
+
49
+ // 添加列定义
50
+ const columnDefs = columns.map(col => ` ${col}`).join(',\n');
51
+ ddl += columnDefs;
52
+
53
+ // 添加主键
54
+ if (primaryKey) {
55
+ ddl += `,\n PRIMARY KEY (${primaryKey})`;
56
+ }
57
+
58
+ ddl += `\n);`;
59
+
60
+ // 添加表注释
61
+ if (jsonSchema.description) {
62
+ ddl += `\n\nCOMMENT ON TABLE ${fullTableName} IS '${this._escapeString(jsonSchema.description)}';`;
63
+ }
64
+
65
+ // 添加列注释
66
+ const commentDdls = this._generateColumnComments(fullTableName, jsonSchema);
67
+ if (commentDdls.length > 0) {
68
+ ddl += '\n\n' + commentDdls.join('\n');
69
+ }
70
+
71
+ return ddl;
72
+ }
73
+
74
+ /**
75
+ * 转换properties为列定义
76
+ * @private
77
+ * @param {Object} schema - JSON Schema对象
78
+ * @returns {Array<string>} 列定义数组
79
+ */
80
+ _convertProperties(schema) {
81
+ if (!schema.properties) {
82
+ return [];
83
+ }
84
+
85
+ const columns = [];
86
+ const required = schema.required || [];
87
+
88
+ for (const [name, propSchema] of Object.entries(schema.properties)) {
89
+ const columnDef = this._convertColumn(name, propSchema, required.includes(name));
90
+ columns.push(columnDef);
91
+ }
92
+
93
+ return columns;
94
+ }
95
+
96
+ /**
97
+ * 转换单个列
98
+ * @private
99
+ * @param {string} name - 列名
100
+ * @param {Object} schema - 属性Schema
101
+ * @param {boolean} isRequired - 是否必填
102
+ * @returns {string} 列定义字符串
103
+ */
104
+ _convertColumn(name, schema, isRequired) {
105
+ const constraints = TypeConverter.extractConstraints(schema);
106
+ const pgType = TypeConverter.toPostgreSQLType(schema.type, constraints);
107
+
108
+ let def = `${name} ${pgType}`;
109
+
110
+ // NULL约束
111
+ if (isRequired) {
112
+ def += ' NOT NULL';
113
+ }
114
+
115
+ // 默认值
116
+ if (schema.default !== undefined) {
117
+ const defaultValue = this._formatDefaultValue(schema.default, schema.type);
118
+ def += ` DEFAULT ${defaultValue}`;
119
+ }
120
+
121
+ // UNIQUE约束
122
+ if (schema.format === 'email' || schema.format === 'uuid') {
123
+ // email和uuid通常是唯一的
124
+ // def += ' UNIQUE'; // 可选
125
+ }
126
+
127
+ // CHECK约束
128
+ const checkConstraints = this._generateCheckConstraints(name, schema);
129
+ if (checkConstraints.length > 0) {
130
+ def += ' ' + checkConstraints.join(' ');
131
+ }
132
+
133
+ return def;
134
+ }
135
+
136
+ /**
137
+ * 生成CHECK约束
138
+ * @private
139
+ * @param {string} columnName - 列名
140
+ * @param {Object} schema - 属性Schema
141
+ * @returns {Array<string>} CHECK约束数组
142
+ */
143
+ _generateCheckConstraints(columnName, schema) {
144
+ const checks = [];
145
+
146
+ // 字符串长度
147
+ if (schema.minLength !== undefined || schema.maxLength !== undefined) {
148
+ if (schema.minLength !== undefined && schema.maxLength !== undefined) {
149
+ checks.push(`CHECK (LENGTH(${columnName}) BETWEEN ${schema.minLength} AND ${schema.maxLength})`);
150
+ } else if (schema.minLength !== undefined) {
151
+ checks.push(`CHECK (LENGTH(${columnName}) >= ${schema.minLength})`);
152
+ } else {
153
+ checks.push(`CHECK (LENGTH(${columnName}) <= ${schema.maxLength})`);
154
+ }
155
+ }
156
+
157
+ // 数值范围
158
+ if (schema.minimum !== undefined || schema.maximum !== undefined) {
159
+ if (schema.minimum !== undefined && schema.maximum !== undefined) {
160
+ checks.push(`CHECK (${columnName} BETWEEN ${schema.minimum} AND ${schema.maximum})`);
161
+ } else if (schema.minimum !== undefined) {
162
+ checks.push(`CHECK (${columnName} >= ${schema.minimum})`);
163
+ } else {
164
+ checks.push(`CHECK (${columnName} <= ${schema.maximum})`);
165
+ }
166
+ }
167
+
168
+ // 枚举
169
+ if (schema.enum) {
170
+ const values = schema.enum.map(v => `'${this._escapeString(v)}'`).join(', ');
171
+ checks.push(`CHECK (${columnName} IN (${values}))`);
172
+ }
173
+
174
+ return checks;
175
+ }
176
+
177
+ /**
178
+ * 格式化默认值
179
+ * @private
180
+ * @param {*} value - 默认值
181
+ * @param {string} type - 类型
182
+ * @returns {string} 格式化后的默认值
183
+ */
184
+ _formatDefaultValue(value, type) {
185
+ if (value === null) {
186
+ return 'NULL';
187
+ }
188
+
189
+ if (type === 'string') {
190
+ return `'${this._escapeString(value)}'`;
191
+ }
192
+
193
+ if (type === 'boolean') {
194
+ return value ? 'TRUE' : 'FALSE';
195
+ }
196
+
197
+ if (type === 'object' || type === 'array') {
198
+ return `'${JSON.stringify(value)}'::JSONB`;
199
+ }
200
+
201
+ return value.toString();
202
+ }
203
+
204
+ /**
205
+ * 转义字符串
206
+ * @private
207
+ * @param {string} str - 字符串
208
+ * @returns {string} 转义后的字符串
209
+ */
210
+ _escapeString(str) {
211
+ return str.replace(/'/g, "''");
212
+ }
213
+
214
+ /**
215
+ * 检测主键
216
+ * @private
217
+ * @param {Object} schema - JSON Schema对象
218
+ * @returns {string|null} 主键列名
219
+ */
220
+ _detectPrimaryKey(schema) {
221
+ if (!schema.properties) {
222
+ return null;
223
+ }
224
+
225
+ // 查找名为id或_id的字段
226
+ if (schema.properties.id) {
227
+ return 'id';
228
+ }
229
+ if (schema.properties._id) {
230
+ return '_id';
231
+ }
232
+
233
+ return null;
234
+ }
235
+
236
+ /**
237
+ * 生成列注释
238
+ * @private
239
+ * @param {string} tableName - 表名
240
+ * @param {Object} schema - JSON Schema对象
241
+ * @returns {Array<string>} COMMENT语句数组
242
+ */
243
+ _generateColumnComments(tableName, schema) {
244
+ if (!schema.properties) {
245
+ return [];
246
+ }
247
+
248
+ const comments = [];
249
+
250
+ for (const [name, propSchema] of Object.entries(schema.properties)) {
251
+ if (propSchema.description) {
252
+ comments.push(`COMMENT ON COLUMN ${tableName}.${name} IS '${this._escapeString(propSchema.description)}';`);
253
+ }
254
+ }
255
+
256
+ return comments;
257
+ }
258
+
259
+ /**
260
+ * 生成索引DDL
261
+ * @param {string} tableName - 表名
262
+ * @param {string} columnName - 列名
263
+ * @param {Object} options - 索引选项
264
+ * @returns {string} CREATE INDEX语句
265
+ */
266
+ generateIndex(tableName, columnName, options = {}) {
267
+ const fullTableName = `${this.options.schema}.${tableName}`;
268
+ const indexName = options.name || `idx_${tableName}_${columnName}`;
269
+ const unique = options.unique ? 'UNIQUE ' : '';
270
+ const method = options.method || 'btree'; // btree, hash, gin, gist
271
+
272
+ return `CREATE ${unique}INDEX ${indexName} ON ${fullTableName} USING ${method} (${columnName});`;
273
+ }
274
+
275
+ /**
276
+ * 静态方法:快速导出
277
+ * @static
278
+ * @param {string} tableName - 表名
279
+ * @param {Object} jsonSchema - JSON Schema对象
280
+ * @returns {string} PostgreSQL DDL语句
281
+ */
282
+ static export(tableName, jsonSchema) {
283
+ const exporter = new PostgreSQLExporter();
284
+ return exporter.export(tableName, jsonSchema);
285
+ }
286
+ }
287
+
288
+ module.exports = PostgreSQLExporter;
289
+
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Exporters - 导出器统一导出
3
+ * @module lib/exporters
4
+ */
5
+
6
+ const MongoDBExporter = require('./MongoDBExporter');
7
+ const MySQLExporter = require('./MySQLExporter');
8
+ const PostgreSQLExporter = require('./PostgreSQLExporter');
9
+ const MarkdownExporter = require('./MarkdownExporter');
10
+
11
+ module.exports = {
12
+ MongoDBExporter,
13
+ MySQLExporter,
14
+ PostgreSQLExporter,
15
+ MarkdownExporter,
16
+
17
+ // 别名
18
+ MongoDB: MongoDBExporter,
19
+ MySQL: MySQLExporter,
20
+ PostgreSQL: PostgreSQLExporter,
21
+ Postgres: PostgreSQLExporter,
22
+ Markdown: MarkdownExporter
23
+ };
24
+
@@ -0,0 +1,65 @@
1
+ module.exports = {
2
+ required: '{{#label}} is required',
3
+ type: '{{#label}} should be {{#expected}}, got {{#actual}}',
4
+ min: '{{#label}} length must be at least {{#limit}}',
5
+ max: '{{#label}} length must be at most {{#limit}}',
6
+ length: '{{#label}} length must be exactly {{#expected}}',
7
+ pattern: '{{#label}} format is invalid',
8
+ enum: '{{#label}} must be one of: {{#allowed}}',
9
+ custom: '{{#label}} validation failed: {{#message}}',
10
+ circular: 'Circular reference detected at {{#label}}',
11
+ 'max-depth': 'Maximum recursion depth ({{#depth}}) exceeded at {{#label}}',
12
+ exception: '{{#label}} validation exception: {{#message}}',
13
+
14
+ // Patterns
15
+ 'pattern.phone': 'Invalid phone number',
16
+ 'pattern.phone.international': 'Invalid international phone number',
17
+
18
+ 'pattern.idCard': 'Invalid ID card number',
19
+
20
+ 'pattern.creditCard': 'Invalid credit card number',
21
+ 'pattern.creditCard.visa': 'Invalid Visa card number',
22
+ 'pattern.creditCard.mastercard': 'Invalid Mastercard number',
23
+ 'pattern.creditCard.amex': 'Invalid American Express card number',
24
+ 'pattern.creditCard.discover': 'Invalid Discover card number',
25
+ 'pattern.creditCard.jcb': 'Invalid JCB card number',
26
+ 'pattern.creditCard.unionpay': 'Invalid UnionPay card number',
27
+
28
+ 'pattern.licensePlate': 'Invalid license plate number',
29
+
30
+ 'pattern.postalCode': 'Invalid postal code',
31
+
32
+ 'pattern.passport': 'Invalid passport number',
33
+
34
+ // New Types
35
+ 'pattern.objectId': 'Invalid ObjectId',
36
+ 'pattern.hexColor': 'Invalid Hex Color',
37
+ 'pattern.macAddress': 'Invalid MAC Address',
38
+ 'pattern.cron': 'Invalid Cron Expression',
39
+ 'pattern.slug': 'URL slug can only contain lowercase letters, numbers, and hyphens',
40
+
41
+ // Username & Password
42
+ 'pattern.username': 'Username must start with a letter and contain only letters, numbers, and underscores',
43
+ 'pattern.password.weak': 'Password must be at least 6 characters',
44
+ 'pattern.password.medium': 'Password must be at least 8 characters and contain letters and numbers',
45
+ 'pattern.password.strong': 'Password must be at least 8 characters and contain uppercase, lowercase letters and numbers',
46
+ 'pattern.password.veryStrong': 'Password must be at least 10 characters and contain uppercase, lowercase letters, numbers and special characters',
47
+
48
+ // Unknown error fallback
49
+ 'UNKNOWN_ERROR': 'Unknown validation error',
50
+
51
+ // Custom validation
52
+ 'CUSTOM_VALIDATION_FAILED': 'Validation failed',
53
+ 'ASYNC_VALIDATION_NOT_SUPPORTED': 'Async validation not supported in synchronous validate()',
54
+ 'VALIDATE_MUST_BE_FUNCTION': 'validate must be a function',
55
+
56
+ // Formats
57
+ 'format.email': '{{#label}} must be a valid email address',
58
+ 'format.url': '{{#label}} must be a valid URL',
59
+ 'format.uuid': '{{#label}} must be a valid UUID',
60
+ 'format.date': '{{#label}} must be a valid date (YYYY-MM-DD)',
61
+ 'format.datetime': '{{#label}} must be a valid date-time (ISO 8601)',
62
+ 'format.time': '{{#label}} must be a valid time (HH:mm:ss)',
63
+ 'format.ipv4': '{{#label}} must be a valid IPv4 address',
64
+ 'format.ipv6': '{{#label}} must be a valid IPv6 address'
65
+ };
@@ -0,0 +1,66 @@
1
+ module.exports = {
2
+ required: '{{#label}} es obligatorio',
3
+ type: '{{#label}} debe ser de tipo {{#expected}}, pero se obtuvo {{#actual}}',
4
+ min: 'La longitud de {{#label}} debe ser al menos {{#limit}}',
5
+ max: 'La longitud de {{#label}} debe ser como máximo {{#limit}}',
6
+ length: 'La longitud de {{#label}} debe ser exactamente {{#expected}}',
7
+ pattern: 'El formato de {{#label}} no es válido',
8
+ enum: '{{#label}} debe ser uno de: {{#allowed}}',
9
+ custom: 'Validación fallida para {{#label}}: {{#message}}',
10
+ circular: 'Referencia circular detectada en {{#label}}',
11
+ 'max-depth': 'Profundidad máxima de recursión ({{#depth}}) excedida en {{#label}}',
12
+ exception: 'Excepción de validación en {{#label}}: {{#message}}',
13
+
14
+ // Patterns
15
+ 'pattern.phone': 'Número de teléfono no válido',
16
+ 'pattern.phone.international': 'Número de teléfono internacional no válido',
17
+
18
+ 'pattern.idCard': 'Número de tarjeta de identificación no válido',
19
+
20
+ 'pattern.creditCard': 'Número de tarjeta de crédito no válido',
21
+ 'pattern.creditCard.visa': 'Número de tarjeta Visa no válido',
22
+ 'pattern.creditCard.mastercard': 'Número de Mastercard no válido',
23
+ 'pattern.creditCard.amex': 'Número de tarjeta American Express no válido',
24
+ 'pattern.creditCard.discover': 'Número de tarjeta Discover no válido',
25
+ 'pattern.creditCard.jcb': 'Número de tarjeta JCB no válido',
26
+ 'pattern.creditCard.unionpay': 'Número de tarjeta UnionPay no válido',
27
+
28
+ 'pattern.licensePlate': 'Número de matrícula no válido',
29
+
30
+ 'pattern.postalCode': 'Código postal no válido',
31
+
32
+ 'pattern.passport': 'Número de pasaporte no válido',
33
+
34
+ // New Types
35
+ 'pattern.objectId': 'ObjectId no válido',
36
+ 'pattern.hexColor': 'Color hexadecimal no válido',
37
+ 'pattern.macAddress': 'Dirección MAC no válida',
38
+ 'pattern.cron': 'Expresión Cron no válida',
39
+ 'pattern.slug': 'El slug de URL solo puede contener letras minúsculas, números y guiones',
40
+
41
+ // Username & Password
42
+ 'pattern.username': 'El nombre de usuario debe comenzar con una letra y contener solo letras, números y guiones bajos',
43
+ 'pattern.password.weak': 'La contraseña debe tener al menos 6 caracteres',
44
+ 'pattern.password.medium': 'La contraseña debe tener al menos 8 caracteres y contener letras y números',
45
+ 'pattern.password.strong': 'La contraseña debe tener al menos 8 caracteres y contener letras mayúsculas, minúsculas y números',
46
+ 'pattern.password.veryStrong': 'La contraseña debe tener al menos 10 caracteres y contener letras mayúsculas, minúsculas, números y caracteres especiales',
47
+
48
+ // Unknown error fallback
49
+ 'UNKNOWN_ERROR': 'Error de validación desconocido',
50
+
51
+ // Custom validation
52
+ 'CUSTOM_VALIDATION_FAILED': 'Validación fallida',
53
+ 'ASYNC_VALIDATION_NOT_SUPPORTED': 'La validación asíncrona no es compatible en validate() síncrono',
54
+ 'VALIDATE_MUST_BE_FUNCTION': 'validate debe ser una función',
55
+
56
+ // Formats
57
+ 'format.email': 'Dirección de correo electrónico no válida',
58
+ 'format.url': 'URL no válida',
59
+ 'format.uuid': 'UUID no válido',
60
+ 'format.date': 'Formato de fecha no válido (YYYY-MM-DD)',
61
+ 'format.datetime': 'Formato de fecha y hora no válido (ISO 8601)',
62
+ 'format.time': 'Formato de hora no válido (HH:mm:ss)',
63
+ 'format.ipv4': 'Dirección IPv4 no válida',
64
+ 'format.ipv6': 'Dirección IPv6 no válida'
65
+ };
66
+