@e22m4u/js-repository 0.8.3 → 0.8.5

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.
@@ -2,7 +2,6 @@ import {expect} from 'chai';
2
2
  import {DataType} from './data-type.js';
3
3
  import {format} from '@e22m4u/js-format';
4
4
  import {DatabaseSchema} from '../../../database-schema.js';
5
- import {EmptyValuesService} from '@e22m4u/js-empty-values';
6
5
  import {PropertyUniqueness} from './property-uniqueness.js';
7
6
  import {PropertyUniquenessValidator} from './property-uniqueness-validator.js';
8
7
  import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK} from '../model-definition-utils.js';
@@ -1862,7 +1861,7 @@ describe('PropertyUniquenessValidator', function () {
1862
1861
  expect(invoked).to.be.eq(1);
1863
1862
  });
1864
1863
 
1865
- it('skips uniqueness checking for empty values', async function () {
1864
+ it('skips uniqueness checking for undefined value', async function () {
1866
1865
  const dbs = new DatabaseSchema();
1867
1866
  dbs.defineModel({
1868
1867
  name: 'model',
@@ -1879,10 +1878,34 @@ describe('PropertyUniquenessValidator', function () {
1879
1878
  });
1880
1879
  const puv = dbs.getService(PropertyUniquenessValidator);
1881
1880
  let invoked = 0;
1882
- dbs
1883
- .getService(EmptyValuesService)
1884
- .setEmptyValuesOf(DataType.STRING, ['val2']);
1885
- const modelData = {foo: 'val1', bar: 'val2'};
1881
+ const modelData = {foo: 'val1', bar: undefined};
1882
+ const countMethod = where => {
1883
+ if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
1884
+ invoked++;
1885
+ return 0;
1886
+ };
1887
+ await puv.validate(countMethod, 'create', 'model', modelData);
1888
+ expect(invoked).to.be.eql(1);
1889
+ });
1890
+
1891
+ it('skips uniqueness checking for an empty string', async function () {
1892
+ const dbs = new DatabaseSchema();
1893
+ dbs.defineModel({
1894
+ name: 'model',
1895
+ properties: {
1896
+ foo: {
1897
+ type: DataType.STRING,
1898
+ unique: PropertyUniqueness.SPARSE,
1899
+ },
1900
+ bar: {
1901
+ type: DataType.STRING,
1902
+ unique: PropertyUniqueness.SPARSE,
1903
+ },
1904
+ },
1905
+ });
1906
+ const puv = dbs.getService(PropertyUniquenessValidator);
1907
+ let invoked = 0;
1908
+ const modelData = {foo: 'val1', bar: ''};
1886
1909
  const countMethod = where => {
1887
1910
  if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
1888
1911
  invoked++;
@@ -1976,7 +1999,7 @@ describe('PropertyUniquenessValidator', function () {
1976
1999
  expect(invoked).to.be.eq(1);
1977
2000
  });
1978
2001
 
1979
- it('skips uniqueness checking for empty values', async function () {
2002
+ it('skips uniqueness checking for undefined value', async function () {
1980
2003
  const dbs = new DatabaseSchema();
1981
2004
  dbs.defineModel({
1982
2005
  name: 'model',
@@ -1993,11 +2016,46 @@ describe('PropertyUniquenessValidator', function () {
1993
2016
  });
1994
2017
  const puv = dbs.getService(PropertyUniquenessValidator);
1995
2018
  let invoked = 0;
1996
- dbs
1997
- .getService(EmptyValuesService)
1998
- .setEmptyValuesOf(DataType.STRING, ['val2']);
1999
2019
  const idValue = 1;
2000
- const modelData = {foo: 'val1', bar: 'val2'};
2020
+ const modelData = {foo: 'val1', bar: undefined};
2021
+ const countMethod = where => {
2022
+ if (invoked === 0)
2023
+ expect(where).to.be.eql({
2024
+ [DEF_PK]: {neq: idValue},
2025
+ foo: 'val1',
2026
+ });
2027
+ invoked++;
2028
+ return 0;
2029
+ };
2030
+ await puv.validate(
2031
+ countMethod,
2032
+ 'replaceById',
2033
+ 'model',
2034
+ modelData,
2035
+ idValue,
2036
+ );
2037
+ expect(invoked).to.be.eql(1);
2038
+ });
2039
+
2040
+ it('skips uniqueness checking for an empty string', async function () {
2041
+ const dbs = new DatabaseSchema();
2042
+ dbs.defineModel({
2043
+ name: 'model',
2044
+ properties: {
2045
+ foo: {
2046
+ type: DataType.STRING,
2047
+ unique: PropertyUniqueness.SPARSE,
2048
+ },
2049
+ bar: {
2050
+ type: DataType.STRING,
2051
+ unique: PropertyUniqueness.SPARSE,
2052
+ },
2053
+ },
2054
+ });
2055
+ const puv = dbs.getService(PropertyUniquenessValidator);
2056
+ let invoked = 0;
2057
+ const idValue = 1;
2058
+ const modelData = {foo: 'val1', bar: ''};
2001
2059
  const countMethod = where => {
2002
2060
  if (invoked === 0)
2003
2061
  expect(where).to.be.eql({
@@ -2241,7 +2299,7 @@ describe('PropertyUniquenessValidator', function () {
2241
2299
  expect(invoked).to.be.eq(3);
2242
2300
  });
2243
2301
 
2244
- it('skips uniqueness checking for empty values', async function () {
2302
+ it('skips uniqueness checking for undefined value', async function () {
2245
2303
  const dbs = new DatabaseSchema();
2246
2304
  dbs.defineModel({
2247
2305
  name: 'model',
@@ -2257,12 +2315,54 @@ describe('PropertyUniquenessValidator', function () {
2257
2315
  },
2258
2316
  });
2259
2317
  const puv = dbs.getService(PropertyUniquenessValidator);
2260
- dbs
2261
- .getService(EmptyValuesService)
2262
- .setEmptyValuesOf(DataType.STRING, ['val2']);
2263
2318
  let invoked = 0;
2264
2319
  const idValue = 1;
2265
- const modelData = {[DEF_PK]: idValue, foo: 'val1', bar: 'val2'};
2320
+ const modelData = {
2321
+ [DEF_PK]: idValue,
2322
+ foo: 'val1',
2323
+ bar: undefined,
2324
+ };
2325
+ const countMethod = where => {
2326
+ if (invoked === 0) {
2327
+ expect(where).to.be.eql({[DEF_PK]: idValue});
2328
+ } else if (invoked === 1) {
2329
+ expect(where).to.be.eql({foo: 'val1'});
2330
+ }
2331
+ invoked++;
2332
+ return 0;
2333
+ };
2334
+ await puv.validate(
2335
+ countMethod,
2336
+ 'replaceOrCreate',
2337
+ 'model',
2338
+ modelData,
2339
+ );
2340
+ expect(invoked).to.be.eql(2);
2341
+ });
2342
+
2343
+ it('skips uniqueness checking for an empty string', async function () {
2344
+ const dbs = new DatabaseSchema();
2345
+ dbs.defineModel({
2346
+ name: 'model',
2347
+ properties: {
2348
+ foo: {
2349
+ type: DataType.STRING,
2350
+ unique: PropertyUniqueness.SPARSE,
2351
+ },
2352
+ bar: {
2353
+ type: DataType.STRING,
2354
+ unique: PropertyUniqueness.SPARSE,
2355
+ },
2356
+ },
2357
+ });
2358
+ const puv = dbs.getService(PropertyUniquenessValidator);
2359
+ let invoked = 0;
2360
+ const idValue = 1;
2361
+ const modelData = {
2362
+ [DEF_PK]: idValue,
2363
+ foo: 'val1',
2364
+ bar: undefined,
2365
+ };
2266
2366
  const countMethod = where => {
2267
2367
  if (invoked === 0) {
2268
2368
  expect(where).to.be.eql({[DEF_PK]: idValue});
@@ -2420,7 +2520,7 @@ describe('PropertyUniquenessValidator', function () {
2420
2520
  expect(invoked).to.be.eq(3);
2421
2521
  });
2422
2522
 
2423
- it('skips uniqueness checking for empty values', async function () {
2523
+ it('skips uniqueness checking for undefined value', async function () {
2424
2524
  const dbs = new DatabaseSchema();
2425
2525
  dbs.defineModel({
2426
2526
  name: 'model',
@@ -2436,12 +2536,58 @@ describe('PropertyUniquenessValidator', function () {
2436
2536
  },
2437
2537
  });
2438
2538
  const puv = dbs.getService(PropertyUniquenessValidator);
2439
- dbs
2440
- .getService(EmptyValuesService)
2441
- .setEmptyValuesOf(DataType.STRING, ['val2']);
2442
2539
  let invoked = 0;
2443
2540
  const idValue = 1;
2444
- const modelData = {[DEF_PK]: idValue, foo: 'val1', bar: 'val2'};
2541
+ const modelData = {
2542
+ [DEF_PK]: idValue,
2543
+ foo: 'val1',
2544
+ bar: undefined,
2545
+ };
2546
+ const countMethod = where => {
2547
+ invoked++;
2548
+ if (invoked === 1) {
2549
+ expect(where).to.be.eql({[DEF_PK]: idValue});
2550
+ return 1;
2551
+ } else if (invoked === 2) {
2552
+ expect(where).to.be.eql({
2553
+ [DEF_PK]: {neq: idValue},
2554
+ foo: 'val1',
2555
+ });
2556
+ return 0;
2557
+ }
2558
+ };
2559
+ await puv.validate(
2560
+ countMethod,
2561
+ 'replaceOrCreate',
2562
+ 'model',
2563
+ modelData,
2564
+ );
2565
+ expect(invoked).to.be.eql(2);
2566
+ });
2567
+
2568
+ it('skips uniqueness checking for an empty string', async function () {
2569
+ const dbs = new DatabaseSchema();
2570
+ dbs.defineModel({
2571
+ name: 'model',
2572
+ properties: {
2573
+ foo: {
2574
+ type: DataType.STRING,
2575
+ unique: PropertyUniqueness.SPARSE,
2576
+ },
2577
+ bar: {
2578
+ type: DataType.STRING,
2579
+ unique: PropertyUniqueness.SPARSE,
2580
+ },
2581
+ },
2582
+ });
2583
+ const puv = dbs.getService(PropertyUniquenessValidator);
2584
+ let invoked = 0;
2585
+ const idValue = 1;
2586
+ const modelData = {
2587
+ [DEF_PK]: idValue,
2588
+ foo: 'val1',
2589
+ bar: '',
2590
+ };
2445
2591
  const countMethod = where => {
2446
2592
  invoked++;
2447
2593
  if (invoked === 1) {
@@ -2558,7 +2704,7 @@ describe('PropertyUniquenessValidator', function () {
2558
2704
  await expect(promise2).not.to.be.rejected;
2559
2705
  });
2560
2706
 
2561
- it('skips uniqueness checking for empty values', async function () {
2707
+ it('skips uniqueness checking for undefined value', async function () {
2562
2708
  const dbs = new DatabaseSchema();
2563
2709
  dbs.defineModel({
2564
2710
  name: 'model',
@@ -2574,11 +2720,35 @@ describe('PropertyUniquenessValidator', function () {
2574
2720
  },
2575
2721
  });
2576
2722
  const puv = dbs.getService(PropertyUniquenessValidator);
2577
- dbs
2578
- .getService(EmptyValuesService)
2579
- .setEmptyValuesOf(DataType.STRING, ['val2']);
2580
2723
  let invoked = 0;
2581
- const modelData = {foo: 'val1', bar: 'val2'};
2724
+ const modelData = {foo: 'val1', bar: undefined};
2725
+ const countMethod = where => {
2726
+ if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
2727
+ invoked++;
2728
+ return 0;
2729
+ };
2730
+ await puv.validate(countMethod, 'patch', 'model', modelData);
2731
+ expect(invoked).to.be.eql(1);
2732
+ });
2733
+
2734
+ it('skips uniqueness checking for an empty string', async function () {
2735
+ const dbs = new DatabaseSchema();
2736
+ dbs.defineModel({
2737
+ name: 'model',
2738
+ properties: {
2739
+ foo: {
2740
+ type: DataType.STRING,
2741
+ unique: PropertyUniqueness.SPARSE,
2742
+ },
2743
+ bar: {
2744
+ type: DataType.STRING,
2745
+ unique: PropertyUniqueness.SPARSE,
2746
+ },
2747
+ },
2748
+ });
2749
+ const puv = dbs.getService(PropertyUniquenessValidator);
2750
+ let invoked = 0;
2751
+ const modelData = {foo: 'val1', bar: ''};
2582
2752
  const countMethod = where => {
2583
2753
  if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
2584
2754
  invoked++;
@@ -2697,7 +2867,7 @@ describe('PropertyUniquenessValidator', function () {
2697
2867
  await expect(promise2).not.to.be.rejected;
2698
2868
  });
2699
2869
 
2700
- it('skips uniqueness checking for empty values', async function () {
2870
+ it('skips uniqueness checking for undefined value', async function () {
2701
2871
  const dbs = new DatabaseSchema();
2702
2872
  dbs.defineModel({
2703
2873
  name: 'model',
@@ -2714,10 +2884,38 @@ describe('PropertyUniquenessValidator', function () {
2714
2884
  });
2715
2885
  const puv = dbs.getService(PropertyUniquenessValidator);
2716
2886
  let invoked = 0;
2717
- dbs
2718
- .getService(EmptyValuesService)
2719
- .setEmptyValuesOf(DataType.STRING, ['val2']);
2720
- const modelData = {foo: 'val1', bar: 'val2'};
2887
+ const modelData = {foo: 'val1', bar: undefined};
2888
+ const countMethod = where => {
2889
+ if (invoked === 0)
2890
+ expect(where).to.be.eql({
2891
+ [DEF_PK]: {neq: 1},
2892
+ foo: 'val1',
2893
+ });
2894
+ invoked++;
2895
+ return 0;
2896
+ };
2897
+ await puv.validate(countMethod, 'patchById', 'model', modelData, 1);
2898
+ expect(invoked).to.be.eql(1);
2899
+ });
2900
+
2901
+ it('skips uniqueness checking for an empty string', async function () {
2902
+ const dbs = new DatabaseSchema();
2903
+ dbs.defineModel({
2904
+ name: 'model',
2905
+ properties: {
2906
+ foo: {
2907
+ type: DataType.STRING,
2908
+ unique: PropertyUniqueness.SPARSE,
2909
+ },
2910
+ bar: {
2911
+ type: DataType.STRING,
2912
+ unique: PropertyUniqueness.SPARSE,
2913
+ },
2914
+ },
2915
+ });
2916
+ const puv = dbs.getService(PropertyUniquenessValidator);
2917
+ let invoked = 0;
2918
+ const modelData = {foo: 'val1', bar: ''};
2721
2919
  const countMethod = where => {
2722
2920
  if (invoked === 0)
2723
2921
  expect(where).to.be.eql({
@@ -0,0 +1,15 @@
1
+ import {Service} from '@e22m4u/js-service';
2
+
3
+ /**
4
+ * Required property validator.
5
+ */
6
+ export class RequiredPropertyValidator extends Service {
7
+ /**
8
+ * Validate.
9
+ *
10
+ * @param modelName
11
+ * @param modelData
12
+ * @param isPartial
13
+ */
14
+ validate(modelName: string, modelData: object, isPartial?: boolean): void;
15
+ }
@@ -0,0 +1,90 @@
1
+ import {DataType} from './data-type.js';
2
+ import {Service} from '@e22m4u/js-service';
3
+ import {InvalidArgumentError} from '../../../errors/index.js';
4
+ import {ModelDefinitionUtils} from '../model-definition-utils.js';
5
+
6
+ /**
7
+ * Required property validator.
8
+ */
9
+ export class RequiredPropertyValidator extends Service {
10
+ /**
11
+ * Validate.
12
+ *
13
+ * @param {string} modelName
14
+ * @param {object} modelData
15
+ * @param {boolean} [isPartial]
16
+ */
17
+ validate(modelName, modelData, isPartial = false) {
18
+ if (!modelName || typeof modelName !== 'string') {
19
+ throw new InvalidArgumentError(
20
+ 'Parameter "modelName" must be a non-empty String, but %v was given.',
21
+ modelName,
22
+ );
23
+ }
24
+ if (
25
+ !modelData ||
26
+ typeof modelData !== 'object' ||
27
+ Array.isArray(modelData)
28
+ ) {
29
+ throw new InvalidArgumentError(
30
+ 'Data of the model %v should be an Object, but %v was given.',
31
+ modelName,
32
+ modelData,
33
+ );
34
+ }
35
+ if (typeof isPartial !== 'boolean') {
36
+ throw new InvalidArgumentError(
37
+ 'Parameter "isPartial" must be a Boolean, but %v was given.',
38
+ isPartial,
39
+ );
40
+ }
41
+ const propDefs =
42
+ this.getService(
43
+ ModelDefinitionUtils,
44
+ ).getPropertiesDefinitionInBaseModelHierarchy(modelName);
45
+ const propNames = Object.keys(isPartial ? modelData : propDefs);
46
+ for (const propName of propNames) {
47
+ const propDef = propDefs[propName];
48
+ if (!propDef || typeof propDef !== 'object') {
49
+ continue;
50
+ }
51
+ // проверка основного значения
52
+ const propValue = modelData[propName];
53
+ if (propDef.required && propValue == null) {
54
+ throw new InvalidArgumentError(
55
+ 'Property %v of the model %v is required, but %v was given.',
56
+ propName,
57
+ modelName,
58
+ propValue,
59
+ );
60
+ }
61
+ // проверка вложенного объекта
62
+ if (
63
+ propDef.type === DataType.OBJECT &&
64
+ propDef.model &&
65
+ propValue !== null &&
66
+ typeof propValue === 'object' &&
67
+ !Array.isArray(propValue)
68
+ ) {
69
+ this.validate(propDef.model, propValue);
70
+ }
71
+ // проверка массива объектов
72
+ else if (
73
+ propDef.type === DataType.ARRAY &&
74
+ propDef.itemType === DataType.OBJECT &&
75
+ propDef.itemModel &&
76
+ Array.isArray(propValue)
77
+ ) {
78
+ propValue.forEach(itemData => {
79
+ if (
80
+ itemData !== null &&
81
+ typeof itemData === 'object' &&
82
+ !Array.isArray(itemData)
83
+ ) {
84
+ this.validate(propDef.itemModel, itemData);
85
+ }
86
+ });
87
+ }
88
+ }
89
+ }
90
+ }