schema-dsl 1.0.0 → 1.0.4
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 +263 -529
- package/README.md +814 -896
- package/STATUS.md +135 -2
- package/docs/INDEX.md +1 -2
- package/docs/api-reference.md +1 -292
- package/docs/custom-extensions-guide.md +411 -0
- package/docs/enum.md +475 -0
- package/docs/i18n.md +394 -0
- package/docs/performance-benchmark-report.md +179 -0
- package/docs/plugin-system.md +8 -8
- package/docs/typescript-guide.md +554 -0
- package/docs/validate-async.md +1 -1
- package/docs/validation-rules-v1.0.2.md +1601 -0
- package/examples/README.md +81 -0
- package/examples/enum.examples.js +324 -0
- package/examples/express-integration.js +54 -54
- package/examples/i18n-full-demo.js +15 -24
- package/examples/schema-utils-chaining.examples.js +2 -2
- package/examples/slug.examples.js +179 -0
- package/index.d.ts +246 -17
- package/index.js +30 -34
- package/lib/config/constants.js +1 -1
- package/lib/config/patterns/common.js +47 -0
- package/lib/config/patterns/index.js +2 -1
- package/lib/core/DslBuilder.js +500 -8
- package/lib/core/StringExtensions.js +31 -0
- package/lib/core/Validator.js +42 -15
- package/lib/errors/ValidationError.js +3 -3
- package/lib/locales/en-US.js +79 -19
- package/lib/locales/es-ES.js +60 -19
- package/lib/locales/fr-FR.js +84 -43
- package/lib/locales/ja-JP.js +83 -42
- package/lib/locales/zh-CN.js +32 -0
- package/lib/validators/CustomKeywords.js +405 -0
- package/package.json +1 -1
- package/.github/CODE_OF_CONDUCT.md +0 -45
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -57
- package/.github/ISSUE_TEMPLATE/config.yml +0 -11
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -45
- package/.github/ISSUE_TEMPLATE/question.md +0 -31
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -70
- package/.github/SECURITY.md +0 -184
- package/.github/workflows/ci.yml +0 -33
- package/plugins/custom-format.js +0 -101
- package/plugins/custom-validator.js +0 -200
|
@@ -25,6 +25,12 @@ class CustomKeywords {
|
|
|
25
25
|
this.registerRangeKeyword(ajv);
|
|
26
26
|
this.registerCustomValidatorsKeyword(ajv);
|
|
27
27
|
this.registerMetadataKeywords(ajv);
|
|
28
|
+
// 新增验证器(v1.0.2)
|
|
29
|
+
this.registerStringValidators(ajv);
|
|
30
|
+
this.registerNumberValidators(ajv);
|
|
31
|
+
this.registerObjectValidators(ajv);
|
|
32
|
+
this.registerArrayValidators(ajv);
|
|
33
|
+
this.registerDateValidators(ajv);
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
/**
|
|
@@ -197,6 +203,405 @@ class CustomKeywords {
|
|
|
197
203
|
errors: true
|
|
198
204
|
});
|
|
199
205
|
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* 注册 String 类型验证器(v1.0.2新增)
|
|
209
|
+
* @static
|
|
210
|
+
* @param {Ajv} ajv - ajv实例
|
|
211
|
+
*/
|
|
212
|
+
static registerStringValidators(ajv) {
|
|
213
|
+
// exactLength: 精确长度验证
|
|
214
|
+
ajv.addKeyword({
|
|
215
|
+
keyword: 'exactLength',
|
|
216
|
+
type: 'string',
|
|
217
|
+
schemaType: 'number',
|
|
218
|
+
validate: function validate(schema, data) {
|
|
219
|
+
if (data.length !== schema) {
|
|
220
|
+
validate.errors = [{
|
|
221
|
+
keyword: 'exactLength',
|
|
222
|
+
message: `string.length`,
|
|
223
|
+
params: { limit: schema }
|
|
224
|
+
}];
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
return true;
|
|
228
|
+
},
|
|
229
|
+
errors: true
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// alphanum: 只能包含字母和数字
|
|
233
|
+
ajv.addKeyword({
|
|
234
|
+
keyword: 'alphanum',
|
|
235
|
+
type: 'string',
|
|
236
|
+
schemaType: 'boolean',
|
|
237
|
+
validate: function validate(schema, data) {
|
|
238
|
+
if (schema && !/^[a-zA-Z0-9]*$/.test(data)) {
|
|
239
|
+
validate.errors = [{
|
|
240
|
+
keyword: 'alphanum',
|
|
241
|
+
message: 'string.alphanum',
|
|
242
|
+
params: {}
|
|
243
|
+
}];
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
return true;
|
|
247
|
+
},
|
|
248
|
+
errors: true
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// trim: 不能包含前后空格
|
|
252
|
+
ajv.addKeyword({
|
|
253
|
+
keyword: 'trim',
|
|
254
|
+
type: 'string',
|
|
255
|
+
schemaType: 'boolean',
|
|
256
|
+
validate: function validate(schema, data) {
|
|
257
|
+
if (schema && data !== data.trim()) {
|
|
258
|
+
validate.errors = [{
|
|
259
|
+
keyword: 'trim',
|
|
260
|
+
message: 'string.trim',
|
|
261
|
+
params: {}
|
|
262
|
+
}];
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
return true;
|
|
266
|
+
},
|
|
267
|
+
errors: true
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// lowercase: 必须是小写
|
|
271
|
+
ajv.addKeyword({
|
|
272
|
+
keyword: 'lowercase',
|
|
273
|
+
type: 'string',
|
|
274
|
+
schemaType: 'boolean',
|
|
275
|
+
validate: function validate(schema, data) {
|
|
276
|
+
if (schema && data !== data.toLowerCase()) {
|
|
277
|
+
validate.errors = [{
|
|
278
|
+
keyword: 'lowercase',
|
|
279
|
+
message: 'string.lowercase',
|
|
280
|
+
params: {}
|
|
281
|
+
}];
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
},
|
|
286
|
+
errors: true
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// uppercase: 必须是大写
|
|
290
|
+
ajv.addKeyword({
|
|
291
|
+
keyword: 'uppercase',
|
|
292
|
+
type: 'string',
|
|
293
|
+
schemaType: 'boolean',
|
|
294
|
+
validate: function validate(schema, data) {
|
|
295
|
+
if (schema && data !== data.toUpperCase()) {
|
|
296
|
+
validate.errors = [{
|
|
297
|
+
keyword: 'uppercase',
|
|
298
|
+
message: 'string.uppercase',
|
|
299
|
+
params: {}
|
|
300
|
+
}];
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
304
|
+
},
|
|
305
|
+
errors: true
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// jsonString: JSON字符串验证
|
|
309
|
+
ajv.addKeyword({
|
|
310
|
+
keyword: 'jsonString',
|
|
311
|
+
type: 'string',
|
|
312
|
+
schemaType: 'boolean',
|
|
313
|
+
validate: function validate(schema, data) {
|
|
314
|
+
if (schema) {
|
|
315
|
+
try {
|
|
316
|
+
JSON.parse(data);
|
|
317
|
+
return true;
|
|
318
|
+
} catch (error) {
|
|
319
|
+
validate.errors = [{
|
|
320
|
+
keyword: 'jsonString',
|
|
321
|
+
message: 'pattern.json',
|
|
322
|
+
params: {}
|
|
323
|
+
}];
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return true;
|
|
328
|
+
},
|
|
329
|
+
errors: true
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* 注册 Number 类型验证器(v1.0.2新增)
|
|
335
|
+
* @static
|
|
336
|
+
* @param {Ajv} ajv - ajv实例
|
|
337
|
+
*/
|
|
338
|
+
static registerNumberValidators(ajv) {
|
|
339
|
+
// precision: 小数位数限制
|
|
340
|
+
ajv.addKeyword({
|
|
341
|
+
keyword: 'precision',
|
|
342
|
+
type: 'number',
|
|
343
|
+
schemaType: 'number',
|
|
344
|
+
validate: function validate(schema, data) {
|
|
345
|
+
const decimalPart = String(data).split('.')[1];
|
|
346
|
+
const actualPrecision = decimalPart ? decimalPart.length : 0;
|
|
347
|
+
|
|
348
|
+
if (actualPrecision > schema) {
|
|
349
|
+
validate.errors = [{
|
|
350
|
+
keyword: 'precision',
|
|
351
|
+
message: 'number.precision',
|
|
352
|
+
params: { limit: schema }
|
|
353
|
+
}];
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
return true;
|
|
357
|
+
},
|
|
358
|
+
errors: true
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// port: 端口号验证 (1-65535)
|
|
362
|
+
ajv.addKeyword({
|
|
363
|
+
keyword: 'port',
|
|
364
|
+
type: ['integer', 'number'],
|
|
365
|
+
schemaType: 'boolean',
|
|
366
|
+
validate: function validate(schema, data) {
|
|
367
|
+
if (schema && (data < 1 || data > 65535 || !Number.isInteger(data))) {
|
|
368
|
+
validate.errors = [{
|
|
369
|
+
keyword: 'port',
|
|
370
|
+
message: 'number.port',
|
|
371
|
+
params: {}
|
|
372
|
+
}];
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
return true;
|
|
376
|
+
},
|
|
377
|
+
errors: true
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* 注册 Object 类型验证器(v1.0.2新增)
|
|
383
|
+
* @static
|
|
384
|
+
* @param {Ajv} ajv - ajv实例
|
|
385
|
+
*/
|
|
386
|
+
static registerObjectValidators(ajv) {
|
|
387
|
+
// requiredAll: 要求所有定义的属性都必须存在
|
|
388
|
+
ajv.addKeyword({
|
|
389
|
+
keyword: 'requiredAll',
|
|
390
|
+
type: 'object',
|
|
391
|
+
schemaType: 'boolean',
|
|
392
|
+
validate: function validate(schema, data, parentSchema) {
|
|
393
|
+
if (!schema) return true;
|
|
394
|
+
|
|
395
|
+
const properties = parentSchema.properties;
|
|
396
|
+
if (!properties) return true;
|
|
397
|
+
|
|
398
|
+
const missingKeys = Object.keys(properties).filter(key => !(key in data));
|
|
399
|
+
|
|
400
|
+
if (missingKeys.length > 0) {
|
|
401
|
+
validate.errors = [{
|
|
402
|
+
keyword: 'requiredAll',
|
|
403
|
+
message: 'object.missing',
|
|
404
|
+
params: { missing: missingKeys }
|
|
405
|
+
}];
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
return true;
|
|
409
|
+
},
|
|
410
|
+
errors: true
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// strictSchema: 严格模式,不允许额外属性
|
|
414
|
+
ajv.addKeyword({
|
|
415
|
+
keyword: 'strictSchema',
|
|
416
|
+
type: 'object',
|
|
417
|
+
schemaType: 'boolean',
|
|
418
|
+
validate: function validate(schema, data, parentSchema) {
|
|
419
|
+
if (!schema) return true;
|
|
420
|
+
|
|
421
|
+
const properties = parentSchema.properties || {};
|
|
422
|
+
const allowedKeys = Object.keys(properties);
|
|
423
|
+
const extraKeys = Object.keys(data).filter(key => !allowedKeys.includes(key));
|
|
424
|
+
|
|
425
|
+
if (extraKeys.length > 0) {
|
|
426
|
+
validate.errors = [{
|
|
427
|
+
keyword: 'strictSchema',
|
|
428
|
+
message: 'object.schema',
|
|
429
|
+
params: { extra: extraKeys }
|
|
430
|
+
}];
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
return true;
|
|
434
|
+
},
|
|
435
|
+
errors: true
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* 注册 Array 类型验证器(v1.0.2新增)
|
|
441
|
+
* @static
|
|
442
|
+
* @param {Ajv} ajv - ajv实例
|
|
443
|
+
*/
|
|
444
|
+
static registerArrayValidators(ajv) {
|
|
445
|
+
// noSparse: 不允许稀疏数组(undefined元素)
|
|
446
|
+
ajv.addKeyword({
|
|
447
|
+
keyword: 'noSparse',
|
|
448
|
+
type: 'array',
|
|
449
|
+
schemaType: 'boolean',
|
|
450
|
+
validate: function validate(schema, data) {
|
|
451
|
+
if (schema) {
|
|
452
|
+
for (let i = 0; i < data.length; i++) {
|
|
453
|
+
if (!(i in data)) {
|
|
454
|
+
validate.errors = [{
|
|
455
|
+
keyword: 'noSparse',
|
|
456
|
+
message: 'array.sparse',
|
|
457
|
+
params: { index: i }
|
|
458
|
+
}];
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return true;
|
|
464
|
+
},
|
|
465
|
+
errors: true
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// includesRequired: 必须包含指定的元素
|
|
469
|
+
ajv.addKeyword({
|
|
470
|
+
keyword: 'includesRequired',
|
|
471
|
+
type: 'array',
|
|
472
|
+
schemaType: 'array',
|
|
473
|
+
validate: function validate(schema, data) {
|
|
474
|
+
if (!Array.isArray(schema) || schema.length === 0) return true;
|
|
475
|
+
|
|
476
|
+
const missing = schema.filter(required => {
|
|
477
|
+
return !data.some(item => {
|
|
478
|
+
if (typeof required === 'object' && required !== null) {
|
|
479
|
+
return JSON.stringify(item) === JSON.stringify(required);
|
|
480
|
+
}
|
|
481
|
+
return item === required;
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
if (missing.length > 0) {
|
|
486
|
+
validate.errors = [{
|
|
487
|
+
keyword: 'includesRequired',
|
|
488
|
+
message: 'array.includesRequired',
|
|
489
|
+
params: { missing }
|
|
490
|
+
}];
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
return true;
|
|
494
|
+
},
|
|
495
|
+
errors: true
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* 注册 Date 类型验证器(v1.0.2新增)
|
|
501
|
+
* @static
|
|
502
|
+
* @param {Ajv} ajv - ajv实例
|
|
503
|
+
*/
|
|
504
|
+
static registerDateValidators(ajv) {
|
|
505
|
+
// dateFormat: 自定义日期格式验证
|
|
506
|
+
ajv.addKeyword({
|
|
507
|
+
keyword: 'dateFormat',
|
|
508
|
+
type: 'string',
|
|
509
|
+
schemaType: 'string',
|
|
510
|
+
validate: function validate(schema, data) {
|
|
511
|
+
// 支持常见格式: YYYY-MM-DD, YYYY/MM/DD, DD-MM-YYYY, DD/MM/YYYY
|
|
512
|
+
const formats = {
|
|
513
|
+
'YYYY-MM-DD': /^\d{4}-\d{2}-\d{2}$/,
|
|
514
|
+
'YYYY/MM/DD': /^\d{4}\/\d{2}\/\d{2}$/,
|
|
515
|
+
'DD-MM-YYYY': /^\d{2}-\d{2}-\d{4}$/,
|
|
516
|
+
'DD/MM/YYYY': /^\d{2}\/\d{2}\/\d{4}$/,
|
|
517
|
+
'ISO8601': /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?$/
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const pattern = formats[schema];
|
|
521
|
+
if (!pattern) {
|
|
522
|
+
validate.errors = [{
|
|
523
|
+
keyword: 'dateFormat',
|
|
524
|
+
message: 'date.format',
|
|
525
|
+
params: { format: schema }
|
|
526
|
+
}];
|
|
527
|
+
return false;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (!pattern.test(data)) {
|
|
531
|
+
validate.errors = [{
|
|
532
|
+
keyword: 'dateFormat',
|
|
533
|
+
message: 'date.format',
|
|
534
|
+
params: { format: schema }
|
|
535
|
+
}];
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
return true;
|
|
539
|
+
},
|
|
540
|
+
errors: true
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
// dateGreater: 日期必须大于指定日期
|
|
544
|
+
ajv.addKeyword({
|
|
545
|
+
keyword: 'dateGreater',
|
|
546
|
+
type: 'string',
|
|
547
|
+
schemaType: 'string',
|
|
548
|
+
validate: function validate(schema, data) {
|
|
549
|
+
const dataDate = new Date(data);
|
|
550
|
+
const compareDate = new Date(schema);
|
|
551
|
+
|
|
552
|
+
if (isNaN(dataDate.getTime()) || isNaN(compareDate.getTime())) {
|
|
553
|
+
validate.errors = [{
|
|
554
|
+
keyword: 'dateGreater',
|
|
555
|
+
message: 'date.greater',
|
|
556
|
+
params: { limit: schema }
|
|
557
|
+
}];
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (dataDate <= compareDate) {
|
|
562
|
+
validate.errors = [{
|
|
563
|
+
keyword: 'dateGreater',
|
|
564
|
+
message: 'date.greater',
|
|
565
|
+
params: { limit: schema }
|
|
566
|
+
}];
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
return true;
|
|
570
|
+
},
|
|
571
|
+
errors: true
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
// dateLess: 日期必须小于指定日期
|
|
575
|
+
ajv.addKeyword({
|
|
576
|
+
keyword: 'dateLess',
|
|
577
|
+
type: 'string',
|
|
578
|
+
schemaType: 'string',
|
|
579
|
+
validate: function validate(schema, data) {
|
|
580
|
+
const dataDate = new Date(data);
|
|
581
|
+
const compareDate = new Date(schema);
|
|
582
|
+
|
|
583
|
+
if (isNaN(dataDate.getTime()) || isNaN(compareDate.getTime())) {
|
|
584
|
+
validate.errors = [{
|
|
585
|
+
keyword: 'dateLess',
|
|
586
|
+
message: 'date.less',
|
|
587
|
+
params: { limit: schema }
|
|
588
|
+
}];
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (dataDate >= compareDate) {
|
|
593
|
+
validate.errors = [{
|
|
594
|
+
keyword: 'dateLess',
|
|
595
|
+
message: 'date.less',
|
|
596
|
+
params: { limit: schema }
|
|
597
|
+
}];
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
return true;
|
|
601
|
+
},
|
|
602
|
+
errors: true
|
|
603
|
+
});
|
|
604
|
+
}
|
|
200
605
|
}
|
|
201
606
|
|
|
202
607
|
module.exports = CustomKeywords;
|
package/package.json
CHANGED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# 贡献者行为准则
|
|
2
|
-
|
|
3
|
-
## 我们的承诺
|
|
4
|
-
|
|
5
|
-
为了营造一个开放和友好的环境,我们作为贡献者和维护者承诺:无论年龄、体型、残疾、民族、性别认同和表达、经验水平、教育程度、社会经济地位、国籍、个人形象、种族、宗教或性取向如何,参与我们的项目和社区的每个人都能获得无骚扰的体验。
|
|
6
|
-
|
|
7
|
-
## 我们的标准
|
|
8
|
-
|
|
9
|
-
有助于创建积极环境的行为包括:
|
|
10
|
-
|
|
11
|
-
* 使用友好和包容的语言
|
|
12
|
-
* 尊重不同的观点和经验
|
|
13
|
-
* 优雅地接受建设性批评
|
|
14
|
-
* 关注对社区最有利的事情
|
|
15
|
-
* 对其他社区成员表示同理心
|
|
16
|
-
|
|
17
|
-
不可接受的行为包括:
|
|
18
|
-
|
|
19
|
-
* 使用性化的语言或图像,以及不受欢迎的性关注或性骚扰
|
|
20
|
-
* 恶意评论、侮辱/贬损性评论以及人身或政治攻击
|
|
21
|
-
* 公开或私下骚扰
|
|
22
|
-
* 未经明确许可,发布他人的私人信息,如物理地址或电子邮件地址
|
|
23
|
-
* 在专业环境中可能被合理认为不适当的其他行为
|
|
24
|
-
|
|
25
|
-
## 我们的责任
|
|
26
|
-
|
|
27
|
-
项目维护者有责任明确可接受行为的标准,并对任何不可接受的行为采取适当和公平的纠正措施。
|
|
28
|
-
|
|
29
|
-
项目维护者有权删除、编辑或拒绝与本行为准则不符的评论、提交、代码、wiki 编辑、问题和其他贡献,或暂时或永久禁止任何贡献者的其他行为,如果他们认为这些行为不适当、威胁、冒犯或有害。
|
|
30
|
-
|
|
31
|
-
## 范围
|
|
32
|
-
|
|
33
|
-
当个人代表项目或其社区时,本行为准则适用于项目空间和公共空间。代表项目或社区的示例包括使用官方项目电子邮件地址、通过官方社交媒体帐户发布信息,或在线上或线下活动中担任指定代表。项目的代表可以由项目维护者进一步定义和澄清。
|
|
34
|
-
|
|
35
|
-
## 执行
|
|
36
|
-
|
|
37
|
-
可以通过联系项目团队 rockyshi1993@gmail.com 报告滥用、骚扰或其他不可接受的行为。所有投诉都将被审查和调查,并将做出被认为必要和适当的回应。项目团队有义务对事件报告者保密。具体执行政策的更多细节可能会单独发布。
|
|
38
|
-
|
|
39
|
-
不善意遵守或执行行为准则的项目维护者可能会面临项目领导层其他成员确定的临时或永久后果。
|
|
40
|
-
|
|
41
|
-
## 归属
|
|
42
|
-
|
|
43
|
-
本行为准则改编自 [Contributor Covenant](https://www.contributor-covenant.org) 版本 2.0,可在 https://www.contributor-covenant.org/version/2/0/code_of_conduct.html 获得。
|
|
44
|
-
|
|
45
|
-
如有关于本行为准则的问题,请参阅 https://www.contributor-covenant.org/faq
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: 🐛 Bug 报告
|
|
3
|
-
about: 报告一个问题帮助我们改进
|
|
4
|
-
title: '[BUG] '
|
|
5
|
-
labels: 'bug'
|
|
6
|
-
assignees: ''
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 🐛 Bug 描述
|
|
10
|
-
|
|
11
|
-
请清晰简洁地描述遇到的问题。
|
|
12
|
-
|
|
13
|
-
## 🔄 重现步骤
|
|
14
|
-
|
|
15
|
-
1. 执行 '...'
|
|
16
|
-
2. 调用 '....'
|
|
17
|
-
3. 看到错误 '....'
|
|
18
|
-
|
|
19
|
-
## ✅ 期望行为
|
|
20
|
-
|
|
21
|
-
描述你期望发生什么。
|
|
22
|
-
|
|
23
|
-
## ❌ 实际行为
|
|
24
|
-
|
|
25
|
-
描述实际发生了什么。
|
|
26
|
-
|
|
27
|
-
## 📝 代码示例
|
|
28
|
-
|
|
29
|
-
```javascript
|
|
30
|
-
const { dsl, validate } = require('schema-dsl');
|
|
31
|
-
|
|
32
|
-
const schema = dsl({
|
|
33
|
-
// 你的 schema 定义
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const result = validate(schema, {
|
|
37
|
-
// 你的测试数据
|
|
38
|
-
});
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## 🌍 环境信息
|
|
42
|
-
|
|
43
|
-
- **schema-dsl 版本**: [例如 v2.3.0]
|
|
44
|
-
- **Node.js 版本**: [例如 v18.0.0]
|
|
45
|
-
- **操作系统**: [例如 Windows 11 / macOS 14 / Ubuntu 22.04]
|
|
46
|
-
- **包管理器**: [npm / yarn / pnpm]
|
|
47
|
-
|
|
48
|
-
## 📎 附加信息
|
|
49
|
-
|
|
50
|
-
添加任何其他有助于解释问题的信息(截图、错误日志等)。
|
|
51
|
-
|
|
52
|
-
## ✔️ 检查清单
|
|
53
|
-
|
|
54
|
-
- [ ] 我已搜索现有 Issues,未发现重复问题
|
|
55
|
-
- [ ] 我已阅读 [文档](https://github.com/vextjs/schema-dsl#readme)
|
|
56
|
-
- [ ] 我已提供完整的重现步骤
|
|
57
|
-
- [ ] 我已提供环境信息
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
blank_issues_enabled: false
|
|
2
|
-
contact_links:
|
|
3
|
-
- name: 📖 查看文档
|
|
4
|
-
url: https://github.com/vextjs/schema-dsl#readme
|
|
5
|
-
about: 查看完整文档和示例
|
|
6
|
-
- name: 💬 讨论区
|
|
7
|
-
url: https://github.com/vextjs/schema-dsl/discussions
|
|
8
|
-
about: 提问、分享想法或参与讨论
|
|
9
|
-
- name: 📝 常见问题
|
|
10
|
-
url: https://github.com/vextjs/schema-dsl/blob/main/docs/faq.md
|
|
11
|
-
about: 查看常见问题解答
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ✨ 功能请求
|
|
3
|
-
about: 建议新功能或改进
|
|
4
|
-
title: '[FEATURE] '
|
|
5
|
-
labels: 'enhancement'
|
|
6
|
-
assignees: ''
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## ✨ 功能描述
|
|
10
|
-
|
|
11
|
-
清晰简洁地描述你希望添加的功能。
|
|
12
|
-
|
|
13
|
-
## 🎯 使用场景
|
|
14
|
-
|
|
15
|
-
**遇到的问题**:
|
|
16
|
-
描述你遇到的问题或限制(例如:"我总是需要..."或"无法实现...")
|
|
17
|
-
|
|
18
|
-
**期望的解决方案**:
|
|
19
|
-
描述你希望如何解决这个问题。
|
|
20
|
-
|
|
21
|
-
## 💡 API 设计建议(可选)
|
|
22
|
-
|
|
23
|
-
如果可以,提供你期望的 API 设计:
|
|
24
|
-
|
|
25
|
-
```javascript
|
|
26
|
-
const schema = dsl({
|
|
27
|
-
// 期望的用法示例
|
|
28
|
-
});
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## 🔄 替代方案(可选)
|
|
32
|
-
|
|
33
|
-
描述你考虑过的其他替代方案或功能。
|
|
34
|
-
|
|
35
|
-
## 📚 参考资料(可选)
|
|
36
|
-
|
|
37
|
-
- 其他库的类似功能
|
|
38
|
-
- 相关文档或讨论链接
|
|
39
|
-
- 截图或示意图
|
|
40
|
-
|
|
41
|
-
## ✔️ 检查清单
|
|
42
|
-
|
|
43
|
-
- [ ] 我已搜索现有 Issues,未发现相同的功能请求
|
|
44
|
-
- [ ] 这个功能符合 SchemaIO 的设计理念(简洁、灵活、易用)
|
|
45
|
-
- [ ] 我愿意提交 PR 来实现这个功能(可选)
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ❓ 问题咨询
|
|
3
|
-
about: 询问使用问题或获取帮助
|
|
4
|
-
title: '[QUESTION] '
|
|
5
|
-
labels: 'question'
|
|
6
|
-
assignees: ''
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## ❓ 你的问题
|
|
10
|
-
|
|
11
|
-
清晰描述你的问题。
|
|
12
|
-
|
|
13
|
-
## 🔍 你已经尝试过什么
|
|
14
|
-
|
|
15
|
-
- [ ] 我已查看 [文档](https://github.com/vextjs/schema-dsl#readme)
|
|
16
|
-
- [ ] 我已查看 [FAQ](https://github.com/vextjs/schema-dsl/blob/main/docs/faq.md)
|
|
17
|
-
- [ ] 我已搜索现有 Issues
|
|
18
|
-
|
|
19
|
-
## 📝 代码示例(可选)
|
|
20
|
-
|
|
21
|
-
```javascript
|
|
22
|
-
// 你当前的代码
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## 🎯 你想实现什么
|
|
26
|
-
|
|
27
|
-
描述你的目标或期望的效果。
|
|
28
|
-
|
|
29
|
-
## 📚 相关文档
|
|
30
|
-
|
|
31
|
-
如果你参考了某些文档但仍有疑问,请提供链接。
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# Pull Request
|
|
2
|
-
|
|
3
|
-
## 📝 描述
|
|
4
|
-
|
|
5
|
-
请简要描述这个 PR 的目的和改动内容。
|
|
6
|
-
|
|
7
|
-
## 🔗 关联 Issue
|
|
8
|
-
|
|
9
|
-
关闭 #(issue编号)
|
|
10
|
-
|
|
11
|
-
## 🎯 改动类型
|
|
12
|
-
|
|
13
|
-
请勾选此 PR 的类型:
|
|
14
|
-
|
|
15
|
-
- [ ] 🐛 Bug 修复
|
|
16
|
-
- [ ] ✨ 新功能
|
|
17
|
-
- [ ] 📚 文档更新
|
|
18
|
-
- [ ] 🎨 代码风格/格式化
|
|
19
|
-
- [ ] ♻️ 重构
|
|
20
|
-
- [ ] ⚡ 性能优化
|
|
21
|
-
- [ ] ✅ 测试相关
|
|
22
|
-
- [ ] 🔧 构建/工具配置
|
|
23
|
-
|
|
24
|
-
## 💡 改动详情
|
|
25
|
-
|
|
26
|
-
### 主要改动
|
|
27
|
-
|
|
28
|
-
- 改动点 1
|
|
29
|
-
- 改动点 2
|
|
30
|
-
|
|
31
|
-
### 技术细节(可选)
|
|
32
|
-
|
|
33
|
-
描述技术实现细节。
|
|
34
|
-
|
|
35
|
-
## 🧪 测试
|
|
36
|
-
|
|
37
|
-
请描述你如何测试这些改动:
|
|
38
|
-
|
|
39
|
-
- [ ] 单元测试通过
|
|
40
|
-
- [ ] 集成测试通过
|
|
41
|
-
- [ ] 手动测试场景:
|
|
42
|
-
|
|
43
|
-
```javascript
|
|
44
|
-
// 测试代码示例
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## 📸 截图(如适用)
|
|
48
|
-
|
|
49
|
-
如果是 UI 相关或有视觉效果的改动,请提供截图。
|
|
50
|
-
|
|
51
|
-
## ✔️ 检查清单
|
|
52
|
-
|
|
53
|
-
在提交前请确认:
|
|
54
|
-
|
|
55
|
-
- [ ] 我的代码遵循项目的代码规范
|
|
56
|
-
- [ ] 我已进行自我审查
|
|
57
|
-
- [ ] 我已添加必要的注释(特别是复杂的逻辑)
|
|
58
|
-
- [ ] 我已更新相关文档
|
|
59
|
-
- [ ] 我的改动没有产生新的警告
|
|
60
|
-
- [ ] 我已添加测试证明我的修复有效或功能正常
|
|
61
|
-
- [ ] 新增和现有的单元测试都通过
|
|
62
|
-
- [ ] 我已更新 CHANGELOG.md(如适用)
|
|
63
|
-
|
|
64
|
-
## 🤔 其他信息
|
|
65
|
-
|
|
66
|
-
添加任何其他相关信息。
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
感谢你的贡献! ❤️
|