@e22m4u/js-repository 0.8.4 → 0.8.6

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 (47) hide show
  1. package/README.md +37 -49
  2. package/dist/cjs/index.cjs +762 -353
  3. package/eslint.config.js +1 -0
  4. package/package.json +14 -14
  5. package/src/adapter/adapter-loader.js +9 -4
  6. package/src/adapter/adapter-registry.js +3 -1
  7. package/src/adapter/builtin/memory-adapter.js +29 -13
  8. package/src/adapter/decorator/data-sanitizing-decorator.js +2 -1
  9. package/src/adapter/decorator/default-values-decorator.js +2 -1
  10. package/src/adapter/decorator/fields-filtering-decorator.js +14 -7
  11. package/src/adapter/decorator/inclusion-decorator.js +14 -7
  12. package/src/adapter/decorator/property-uniqueness-decorator.js +2 -1
  13. package/src/adapter/decorator/required-property-decorator.js +2 -1
  14. package/src/definition/datasource/datasource-definition-validator.js +6 -3
  15. package/src/definition/definition-registry.js +8 -4
  16. package/src/definition/model/model-data-sanitizer.js +4 -2
  17. package/src/definition/model/model-definition-utils.js +74 -35
  18. package/src/definition/model/model-definition-utils.spec.js +2 -6
  19. package/src/definition/model/model-definition-validator.js +10 -5
  20. package/src/definition/model/properties/primary-keys-definition-validator.js +4 -2
  21. package/src/definition/model/properties/properties-definition-validator.js +36 -18
  22. package/src/definition/model/properties/property-uniqueness-validator.js +30 -18
  23. package/src/definition/model/properties/property-uniqueness-validator.spec.js +734 -74
  24. package/src/definition/model/properties/required-property-validator.js +7 -12
  25. package/src/definition/model/properties/required-property-validator.spec.js +7 -46
  26. package/src/definition/model/relations/relations-definition-validator.js +70 -33
  27. package/src/filter/fields-clause-tool.js +31 -12
  28. package/src/filter/include-clause-tool.js +38 -15
  29. package/src/filter/operator-clause-tool.js +55 -23
  30. package/src/filter/order-clause-tool.js +36 -13
  31. package/src/filter/slice-clause-tool.js +16 -7
  32. package/src/filter/where-clause-tool.js +24 -10
  33. package/src/relations/belongs-to-resolver.js +44 -20
  34. package/src/relations/has-many-resolver.js +52 -25
  35. package/src/relations/has-one-resolver.js +58 -27
  36. package/src/relations/references-many-resolver.js +24 -11
  37. package/src/repository/repository-registry.js +3 -1
  38. package/src/repository/repository.js +2 -1
  39. package/src/utils/capitalize.js +3 -1
  40. package/src/utils/clone-deep.js +6 -2
  41. package/src/utils/exclude-object-keys.js +2 -1
  42. package/src/utils/get-value-by-path.js +6 -2
  43. package/src/utils/is-deep-equal.js +21 -7
  44. package/src/utils/is-promise.js +6 -2
  45. package/src/utils/model-name-to-model-key.js +2 -1
  46. package/src/utils/select-object-keys.js +9 -4
  47. package/src/utils/singularize.js +3 -1
@@ -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 {BlankValuesService} 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';
@@ -430,11 +429,12 @@ describe('PropertyUniquenessValidator', function () {
430
429
  const idValue = 1;
431
430
  const modelData = {foo: 'bar'};
432
431
  const countMethod = where => {
433
- if (invoked === 0)
432
+ if (invoked === 0) {
434
433
  expect(where).to.be.eql({
435
434
  myId: {neq: idValue},
436
435
  foo: 'bar',
437
436
  });
437
+ }
438
438
  invoked++;
439
439
  return 0;
440
440
  };
@@ -838,7 +838,9 @@ describe('PropertyUniquenessValidator', function () {
838
838
  let invoked = 0;
839
839
  const modelData = {foo: 'val1', bar: 'val2'};
840
840
  const countMethod = where => {
841
- if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
841
+ if (invoked === 0) {
842
+ expect(where).to.be.eql({foo: 'val1'});
843
+ }
842
844
  invoked++;
843
845
  return 0;
844
846
  };
@@ -937,11 +939,12 @@ describe('PropertyUniquenessValidator', function () {
937
939
  const idValue = 1;
938
940
  const modelData = {foo: 'val1', bar: 'val2'};
939
941
  const countMethod = where => {
940
- if (invoked === 0)
942
+ if (invoked === 0) {
941
943
  expect(where).to.be.eql({
942
944
  [DEF_PK]: {neq: idValue},
943
945
  foo: 'val1',
944
946
  });
947
+ }
945
948
  invoked++;
946
949
  return 0;
947
950
  };
@@ -1000,11 +1003,12 @@ describe('PropertyUniquenessValidator', function () {
1000
1003
  const idValue = 1;
1001
1004
  const modelData = {foo: 'bar'};
1002
1005
  const countMethod = where => {
1003
- if (invoked === 0)
1006
+ if (invoked === 0) {
1004
1007
  expect(where).to.be.eql({
1005
1008
  myId: {neq: idValue},
1006
1009
  foo: 'bar',
1007
1010
  });
1011
+ }
1008
1012
  invoked++;
1009
1013
  return 0;
1010
1014
  };
@@ -1203,11 +1207,12 @@ describe('PropertyUniquenessValidator', function () {
1203
1207
  const idValue = 1;
1204
1208
  const modelData = {foo: 'bar'};
1205
1209
  const countMethod = where => {
1206
- if (invoked === 0)
1210
+ if (invoked === 0) {
1207
1211
  expect(where).to.be.eql({
1208
1212
  myId: {neq: idValue},
1209
1213
  foo: 'bar',
1210
1214
  });
1215
+ }
1211
1216
  invoked++;
1212
1217
  return 0;
1213
1218
  };
@@ -1611,7 +1616,9 @@ describe('PropertyUniquenessValidator', function () {
1611
1616
  let invoked = 0;
1612
1617
  const modelData = {foo: 'val1', bar: 'val2'};
1613
1618
  const countMethod = where => {
1614
- if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
1619
+ if (invoked === 0) {
1620
+ expect(where).to.be.eql({foo: 'val1'});
1621
+ }
1615
1622
  invoked++;
1616
1623
  return 0;
1617
1624
  };
@@ -1710,11 +1717,12 @@ describe('PropertyUniquenessValidator', function () {
1710
1717
  const idValue = 1;
1711
1718
  const modelData = {foo: 'val1', bar: 'val2'};
1712
1719
  const countMethod = where => {
1713
- if (invoked === 0)
1720
+ if (invoked === 0) {
1714
1721
  expect(where).to.be.eql({
1715
1722
  [DEF_PK]: {neq: idValue},
1716
1723
  foo: 'val1',
1717
1724
  });
1725
+ }
1718
1726
  invoked++;
1719
1727
  return 0;
1720
1728
  };
@@ -1773,11 +1781,12 @@ describe('PropertyUniquenessValidator', function () {
1773
1781
  const idValue = 1;
1774
1782
  const modelData = {foo: 'bar'};
1775
1783
  const countMethod = where => {
1776
- if (invoked === 0)
1784
+ if (invoked === 0) {
1777
1785
  expect(where).to.be.eql({
1778
1786
  myId: {neq: idValue},
1779
1787
  foo: 'bar',
1780
1788
  });
1789
+ }
1781
1790
  invoked++;
1782
1791
  return 0;
1783
1792
  };
@@ -1854,7 +1863,9 @@ describe('PropertyUniquenessValidator', function () {
1854
1863
  let invoked = 0;
1855
1864
  const modelData = {foo: 'val1', bar: 'val2'};
1856
1865
  const countMethod = where => {
1857
- if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
1866
+ if (invoked === 0) {
1867
+ expect(where).to.be.eql({foo: 'val1'});
1868
+ }
1858
1869
  invoked++;
1859
1870
  return 0;
1860
1871
  };
@@ -1862,7 +1873,7 @@ describe('PropertyUniquenessValidator', function () {
1862
1873
  expect(invoked).to.be.eq(1);
1863
1874
  });
1864
1875
 
1865
- it('skips uniqueness checking for blank values', async function () {
1876
+ it('skips uniqueness checking for an undefined value', async function () {
1866
1877
  const dbs = new DatabaseSchema();
1867
1878
  dbs.defineModel({
1868
1879
  name: 'model',
@@ -1879,12 +1890,98 @@ describe('PropertyUniquenessValidator', function () {
1879
1890
  });
1880
1891
  const puv = dbs.getService(PropertyUniquenessValidator);
1881
1892
  let invoked = 0;
1882
- dbs
1883
- .getService(BlankValuesService)
1884
- .setBlankValuesOf(DataType.STRING, ['val2']);
1885
- const modelData = {foo: 'val1', bar: 'val2'};
1893
+ const modelData = {foo: 'val1', bar: undefined};
1894
+ const countMethod = where => {
1895
+ if (invoked === 0) {
1896
+ expect(where).to.be.eql({foo: modelData.foo});
1897
+ }
1898
+ invoked++;
1899
+ return 0;
1900
+ };
1901
+ await puv.validate(countMethod, 'create', 'model', modelData);
1902
+ expect(invoked).to.be.eql(1);
1903
+ });
1904
+
1905
+ it('skips uniqueness checking for an empty string', async function () {
1906
+ const dbs = new DatabaseSchema();
1907
+ dbs.defineModel({
1908
+ name: 'model',
1909
+ properties: {
1910
+ foo: {
1911
+ type: DataType.STRING,
1912
+ unique: PropertyUniqueness.SPARSE,
1913
+ },
1914
+ bar: {
1915
+ type: DataType.STRING,
1916
+ unique: PropertyUniqueness.SPARSE,
1917
+ },
1918
+ },
1919
+ });
1920
+ const puv = dbs.getService(PropertyUniquenessValidator);
1921
+ let invoked = 0;
1922
+ const modelData = {foo: 'val1', bar: ''};
1923
+ const countMethod = where => {
1924
+ if (invoked === 0) {
1925
+ expect(where).to.be.eql({foo: modelData.foo});
1926
+ }
1927
+ invoked++;
1928
+ return 0;
1929
+ };
1930
+ await puv.validate(countMethod, 'create', 'model', modelData);
1931
+ expect(invoked).to.be.eql(1);
1932
+ });
1933
+
1934
+ it('skips uniqueness checking for a zero number', async function () {
1935
+ const dbs = new DatabaseSchema();
1936
+ dbs.defineModel({
1937
+ name: 'model',
1938
+ properties: {
1939
+ foo: {
1940
+ type: DataType.NUMBER,
1941
+ unique: PropertyUniqueness.SPARSE,
1942
+ },
1943
+ bar: {
1944
+ type: DataType.NUMBER,
1945
+ unique: PropertyUniqueness.SPARSE,
1946
+ },
1947
+ },
1948
+ });
1949
+ const puv = dbs.getService(PropertyUniquenessValidator);
1950
+ let invoked = 0;
1951
+ const modelData = {foo: 10, bar: 0};
1952
+ const countMethod = where => {
1953
+ if (invoked === 0) {
1954
+ expect(where).to.be.eql({foo: modelData.foo});
1955
+ }
1956
+ invoked++;
1957
+ return 0;
1958
+ };
1959
+ await puv.validate(countMethod, 'create', 'model', modelData);
1960
+ expect(invoked).to.be.eql(1);
1961
+ });
1962
+
1963
+ it('skips uniqueness checking for a false value', async function () {
1964
+ const dbs = new DatabaseSchema();
1965
+ dbs.defineModel({
1966
+ name: 'model',
1967
+ properties: {
1968
+ foo: {
1969
+ type: DataType.BOOLEAN,
1970
+ unique: PropertyUniqueness.SPARSE,
1971
+ },
1972
+ bar: {
1973
+ type: DataType.BOOLEAN,
1974
+ unique: PropertyUniqueness.SPARSE,
1975
+ },
1976
+ },
1977
+ });
1978
+ const puv = dbs.getService(PropertyUniquenessValidator);
1979
+ let invoked = 0;
1980
+ const modelData = {foo: true, bar: false};
1886
1981
  const countMethod = where => {
1887
- if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
1982
+ if (invoked === 0) {
1983
+ expect(where).to.be.eql({foo: modelData.foo});
1984
+ }
1888
1985
  invoked++;
1889
1986
  return 0;
1890
1987
  };
@@ -1958,11 +2055,12 @@ describe('PropertyUniquenessValidator', function () {
1958
2055
  const idValue = 1;
1959
2056
  const modelData = {foo: 'val1', bar: 'val2'};
1960
2057
  const countMethod = where => {
1961
- if (invoked === 0)
2058
+ if (invoked === 0) {
1962
2059
  expect(where).to.be.eql({
1963
2060
  [DEF_PK]: {neq: idValue},
1964
2061
  foo: 'val1',
1965
2062
  });
2063
+ }
1966
2064
  invoked++;
1967
2065
  return 0;
1968
2066
  };
@@ -1976,7 +2074,7 @@ describe('PropertyUniquenessValidator', function () {
1976
2074
  expect(invoked).to.be.eq(1);
1977
2075
  });
1978
2076
 
1979
- it('skips uniqueness checking for blank values', async function () {
2077
+ it('skips uniqueness checking for an undefined value', async function () {
1980
2078
  const dbs = new DatabaseSchema();
1981
2079
  dbs.defineModel({
1982
2080
  name: 'model',
@@ -1993,17 +2091,132 @@ describe('PropertyUniquenessValidator', function () {
1993
2091
  });
1994
2092
  const puv = dbs.getService(PropertyUniquenessValidator);
1995
2093
  let invoked = 0;
1996
- dbs
1997
- .getService(BlankValuesService)
1998
- .setBlankValuesOf(DataType.STRING, ['val2']);
1999
2094
  const idValue = 1;
2000
- const modelData = {foo: 'val1', bar: 'val2'};
2095
+ const modelData = {foo: 'val1', bar: undefined};
2001
2096
  const countMethod = where => {
2002
- if (invoked === 0)
2097
+ if (invoked === 0) {
2003
2098
  expect(where).to.be.eql({
2004
2099
  [DEF_PK]: {neq: idValue},
2005
- foo: 'val1',
2100
+ foo: modelData.foo,
2101
+ });
2102
+ }
2103
+ invoked++;
2104
+ return 0;
2105
+ };
2106
+ await puv.validate(
2107
+ countMethod,
2108
+ 'replaceById',
2109
+ 'model',
2110
+ modelData,
2111
+ idValue,
2112
+ );
2113
+ expect(invoked).to.be.eql(1);
2114
+ });
2115
+
2116
+ it('skips uniqueness checking for an empty string', async function () {
2117
+ const dbs = new DatabaseSchema();
2118
+ dbs.defineModel({
2119
+ name: 'model',
2120
+ properties: {
2121
+ foo: {
2122
+ type: DataType.STRING,
2123
+ unique: PropertyUniqueness.SPARSE,
2124
+ },
2125
+ bar: {
2126
+ type: DataType.STRING,
2127
+ unique: PropertyUniqueness.SPARSE,
2128
+ },
2129
+ },
2130
+ });
2131
+ const puv = dbs.getService(PropertyUniquenessValidator);
2132
+ let invoked = 0;
2133
+ const idValue = 1;
2134
+ const modelData = {foo: 'val1', bar: ''};
2135
+ const countMethod = where => {
2136
+ if (invoked === 0) {
2137
+ expect(where).to.be.eql({
2138
+ [DEF_PK]: {neq: idValue},
2139
+ foo: modelData.foo,
2140
+ });
2141
+ }
2142
+ invoked++;
2143
+ return 0;
2144
+ };
2145
+ await puv.validate(
2146
+ countMethod,
2147
+ 'replaceById',
2148
+ 'model',
2149
+ modelData,
2150
+ idValue,
2151
+ );
2152
+ expect(invoked).to.be.eql(1);
2153
+ });
2154
+
2155
+ it('skips uniqueness checking for a zero number', async function () {
2156
+ const dbs = new DatabaseSchema();
2157
+ dbs.defineModel({
2158
+ name: 'model',
2159
+ properties: {
2160
+ foo: {
2161
+ type: DataType.NUMBER,
2162
+ unique: PropertyUniqueness.SPARSE,
2163
+ },
2164
+ bar: {
2165
+ type: DataType.NUMBER,
2166
+ unique: PropertyUniqueness.SPARSE,
2167
+ },
2168
+ },
2169
+ });
2170
+ const puv = dbs.getService(PropertyUniquenessValidator);
2171
+ let invoked = 0;
2172
+ const idValue = 1;
2173
+ const modelData = {foo: 10, bar: 0};
2174
+ const countMethod = where => {
2175
+ if (invoked === 0) {
2176
+ expect(where).to.be.eql({
2177
+ [DEF_PK]: {neq: idValue},
2178
+ foo: modelData.foo,
2179
+ });
2180
+ }
2181
+ invoked++;
2182
+ return 0;
2183
+ };
2184
+ await puv.validate(
2185
+ countMethod,
2186
+ 'replaceById',
2187
+ 'model',
2188
+ modelData,
2189
+ idValue,
2190
+ );
2191
+ expect(invoked).to.be.eql(1);
2192
+ });
2193
+
2194
+ it('skips uniqueness checking for a false value', async function () {
2195
+ const dbs = new DatabaseSchema();
2196
+ dbs.defineModel({
2197
+ name: 'model',
2198
+ properties: {
2199
+ foo: {
2200
+ type: DataType.BOOLEAN,
2201
+ unique: PropertyUniqueness.SPARSE,
2202
+ },
2203
+ bar: {
2204
+ type: DataType.BOOLEAN,
2205
+ unique: PropertyUniqueness.SPARSE,
2206
+ },
2207
+ },
2208
+ });
2209
+ const puv = dbs.getService(PropertyUniquenessValidator);
2210
+ let invoked = 0;
2211
+ const idValue = 1;
2212
+ const modelData = {foo: true, bar: false};
2213
+ const countMethod = where => {
2214
+ if (invoked === 0) {
2215
+ expect(where).to.be.eql({
2216
+ [DEF_PK]: {neq: idValue},
2217
+ foo: modelData.foo,
2006
2218
  });
2219
+ }
2007
2220
  invoked++;
2008
2221
  return 0;
2009
2222
  };
@@ -2037,11 +2250,12 @@ describe('PropertyUniquenessValidator', function () {
2037
2250
  const idValue = 1;
2038
2251
  const modelData = {foo: 'bar'};
2039
2252
  const countMethod = where => {
2040
- if (invoked === 0)
2253
+ if (invoked === 0) {
2041
2254
  expect(where).to.be.eql({
2042
2255
  myId: {neq: idValue},
2043
2256
  foo: 'bar',
2044
2257
  });
2258
+ }
2045
2259
  invoked++;
2046
2260
  return 0;
2047
2261
  };
@@ -2116,7 +2330,9 @@ describe('PropertyUniquenessValidator', function () {
2116
2330
  let invoked = 0;
2117
2331
  const modelData = {foo: 'val1', bar: 'val2'};
2118
2332
  const countMethod = where => {
2119
- if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
2333
+ if (invoked === 0) {
2334
+ expect(where).to.be.eql({foo: 'val1'});
2335
+ }
2120
2336
  invoked++;
2121
2337
  return 0;
2122
2338
  };
@@ -2241,7 +2457,7 @@ describe('PropertyUniquenessValidator', function () {
2241
2457
  expect(invoked).to.be.eq(3);
2242
2458
  });
2243
2459
 
2244
- it('skips uniqueness checking for blank values', async function () {
2460
+ it('skips uniqueness checking for an undefined value', async function () {
2245
2461
  const dbs = new DatabaseSchema();
2246
2462
  dbs.defineModel({
2247
2463
  name: 'model',
@@ -2257,17 +2473,18 @@ describe('PropertyUniquenessValidator', function () {
2257
2473
  },
2258
2474
  });
2259
2475
  const puv = dbs.getService(PropertyUniquenessValidator);
2260
- dbs
2261
- .getService(BlankValuesService)
2262
- .setBlankValuesOf(DataType.STRING, ['val2']);
2263
2476
  let invoked = 0;
2264
2477
  const idValue = 1;
2265
- const modelData = {[DEF_PK]: idValue, foo: 'val1', bar: 'val2'};
2478
+ const modelData = {
2479
+ [DEF_PK]: idValue,
2480
+ foo: 'val1',
2481
+ bar: undefined,
2482
+ };
2266
2483
  const countMethod = where => {
2267
2484
  if (invoked === 0) {
2268
2485
  expect(where).to.be.eql({[DEF_PK]: idValue});
2269
2486
  } else if (invoked === 1) {
2270
- expect(where).to.be.eql({foo: 'val1'});
2487
+ expect(where).to.be.eql({foo: modelData.foo});
2271
2488
  }
2272
2489
  invoked++;
2273
2490
  return 0;
@@ -2280,16 +2497,18 @@ describe('PropertyUniquenessValidator', function () {
2280
2497
  );
2281
2498
  expect(invoked).to.be.eql(2);
2282
2499
  });
2283
- });
2284
2500
 
2285
- describe('a document of the given identifier already exist', function () {
2286
- it('uses the default primary key to check existence of the given identifier', async function () {
2501
+ it('skips uniqueness checking for an empty string', async function () {
2287
2502
  const dbs = new DatabaseSchema();
2288
2503
  dbs.defineModel({
2289
2504
  name: 'model',
2290
2505
  properties: {
2291
2506
  foo: {
2292
- type: DataType.ANY,
2507
+ type: DataType.STRING,
2508
+ unique: PropertyUniqueness.SPARSE,
2509
+ },
2510
+ bar: {
2511
+ type: DataType.STRING,
2293
2512
  unique: PropertyUniqueness.SPARSE,
2294
2513
  },
2295
2514
  },
@@ -2299,22 +2518,17 @@ describe('PropertyUniquenessValidator', function () {
2299
2518
  const idValue = 1;
2300
2519
  const modelData = {
2301
2520
  [DEF_PK]: idValue,
2302
- foo: 'bar',
2521
+ foo: 'val1',
2522
+ bar: '',
2303
2523
  };
2304
2524
  const countMethod = where => {
2305
- invoked++;
2306
- if (invoked === 1) {
2307
- expect(where).to.be.eql({
2308
- [DEF_PK]: idValue,
2309
- });
2310
- return 1;
2311
- } else if (invoked === 2) {
2312
- expect(where).to.be.eql({
2313
- [DEF_PK]: {neq: idValue},
2314
- foo: 'bar',
2315
- });
2316
- return 0;
2525
+ if (invoked === 0) {
2526
+ expect(where).to.be.eql({[DEF_PK]: idValue});
2527
+ } else if (invoked === 1) {
2528
+ expect(where).to.be.eql({foo: modelData.foo});
2317
2529
  }
2530
+ invoked++;
2531
+ return 0;
2318
2532
  };
2319
2533
  await puv.validate(
2320
2534
  countMethod,
@@ -2322,15 +2536,141 @@ describe('PropertyUniquenessValidator', function () {
2322
2536
  'model',
2323
2537
  modelData,
2324
2538
  );
2325
- expect(invoked).to.be.eq(2);
2539
+ expect(invoked).to.be.eql(2);
2326
2540
  });
2327
2541
 
2328
- it('uses a custom primary key to check existence of the given identifier', async function () {
2542
+ it('skips uniqueness checking for a zero number', async function () {
2329
2543
  const dbs = new DatabaseSchema();
2330
2544
  dbs.defineModel({
2331
2545
  name: 'model',
2332
2546
  properties: {
2333
- myId: {
2547
+ foo: {
2548
+ type: DataType.NUMBER,
2549
+ unique: PropertyUniqueness.SPARSE,
2550
+ },
2551
+ bar: {
2552
+ type: DataType.NUMBER,
2553
+ unique: PropertyUniqueness.SPARSE,
2554
+ },
2555
+ },
2556
+ });
2557
+ const puv = dbs.getService(PropertyUniquenessValidator);
2558
+ let invoked = 0;
2559
+ const idValue = 1;
2560
+ const modelData = {
2561
+ [DEF_PK]: idValue,
2562
+ foo: 10,
2563
+ bar: 0,
2564
+ };
2565
+ const countMethod = where => {
2566
+ if (invoked === 0) {
2567
+ expect(where).to.be.eql({[DEF_PK]: idValue});
2568
+ } else if (invoked === 1) {
2569
+ expect(where).to.be.eql({foo: modelData.foo});
2570
+ }
2571
+ invoked++;
2572
+ return 0;
2573
+ };
2574
+ await puv.validate(
2575
+ countMethod,
2576
+ 'replaceOrCreate',
2577
+ 'model',
2578
+ modelData,
2579
+ );
2580
+ expect(invoked).to.be.eql(2);
2581
+ });
2582
+
2583
+ it('skips uniqueness checking for a false value', async function () {
2584
+ const dbs = new DatabaseSchema();
2585
+ dbs.defineModel({
2586
+ name: 'model',
2587
+ properties: {
2588
+ foo: {
2589
+ type: DataType.BOOLEAN,
2590
+ unique: PropertyUniqueness.SPARSE,
2591
+ },
2592
+ bar: {
2593
+ type: DataType.BOOLEAN,
2594
+ unique: PropertyUniqueness.SPARSE,
2595
+ },
2596
+ },
2597
+ });
2598
+ const puv = dbs.getService(PropertyUniquenessValidator);
2599
+ let invoked = 0;
2600
+ const idValue = 1;
2601
+ const modelData = {
2602
+ [DEF_PK]: idValue,
2603
+ foo: true,
2604
+ bar: false,
2605
+ };
2606
+ const countMethod = where => {
2607
+ if (invoked === 0) {
2608
+ expect(where).to.be.eql({[DEF_PK]: idValue});
2609
+ } else if (invoked === 1) {
2610
+ expect(where).to.be.eql({foo: modelData.foo});
2611
+ }
2612
+ invoked++;
2613
+ return 0;
2614
+ };
2615
+ await puv.validate(
2616
+ countMethod,
2617
+ 'replaceOrCreate',
2618
+ 'model',
2619
+ modelData,
2620
+ );
2621
+ expect(invoked).to.be.eql(2);
2622
+ });
2623
+ });
2624
+
2625
+ describe('a document of the given identifier already exist', function () {
2626
+ it('uses the default primary key to check existence of the given identifier', async function () {
2627
+ const dbs = new DatabaseSchema();
2628
+ dbs.defineModel({
2629
+ name: 'model',
2630
+ properties: {
2631
+ foo: {
2632
+ type: DataType.ANY,
2633
+ unique: PropertyUniqueness.SPARSE,
2634
+ },
2635
+ },
2636
+ });
2637
+ const puv = dbs.getService(PropertyUniquenessValidator);
2638
+ let invoked = 0;
2639
+ const idValue = 1;
2640
+ const modelData = {
2641
+ [DEF_PK]: idValue,
2642
+ foo: 'bar',
2643
+ };
2644
+ const countMethod = where => {
2645
+ invoked++;
2646
+ if (invoked === 1) {
2647
+ expect(where).to.be.eql({
2648
+ [DEF_PK]: idValue,
2649
+ });
2650
+ return 1;
2651
+ } else if (invoked === 2) {
2652
+ expect(where).to.be.eql({
2653
+ [DEF_PK]: {neq: idValue},
2654
+ foo: 'bar',
2655
+ });
2656
+ return 0;
2657
+ }
2658
+ };
2659
+ await puv.validate(
2660
+ countMethod,
2661
+ 'replaceOrCreate',
2662
+ 'model',
2663
+ modelData,
2664
+ );
2665
+ expect(invoked).to.be.eq(2);
2666
+ });
2667
+
2668
+ it('uses a custom primary key to check existence of the given identifier', async function () {
2669
+ const dbs = new DatabaseSchema();
2670
+ dbs.defineModel({
2671
+ name: 'model',
2672
+ properties: {
2673
+ myId: {
2334
2674
  type: DataType.NUMBER,
2335
2675
  primaryKey: true,
2336
2676
  },
@@ -2420,7 +2760,7 @@ describe('PropertyUniquenessValidator', function () {
2420
2760
  expect(invoked).to.be.eq(3);
2421
2761
  });
2422
2762
 
2423
- it('skips uniqueness checking for blank values', async function () {
2763
+ it('skips uniqueness checking for an undefined value', async function () {
2424
2764
  const dbs = new DatabaseSchema();
2425
2765
  dbs.defineModel({
2426
2766
  name: 'model',
@@ -2436,12 +2776,13 @@ describe('PropertyUniquenessValidator', function () {
2436
2776
  },
2437
2777
  });
2438
2778
  const puv = dbs.getService(PropertyUniquenessValidator);
2439
- dbs
2440
- .getService(BlankValuesService)
2441
- .setBlankValuesOf(DataType.STRING, ['val2']);
2442
2779
  let invoked = 0;
2443
2780
  const idValue = 1;
2444
- const modelData = {[DEF_PK]: idValue, foo: 'val1', bar: 'val2'};
2781
+ const modelData = {
2782
+ [DEF_PK]: idValue,
2783
+ foo: 'val1',
2784
+ bar: undefined,
2785
+ };
2445
2786
  const countMethod = where => {
2446
2787
  invoked++;
2447
2788
  if (invoked === 1) {
@@ -2450,7 +2791,142 @@ describe('PropertyUniquenessValidator', function () {
2450
2791
  } else if (invoked === 2) {
2451
2792
  expect(where).to.be.eql({
2452
2793
  [DEF_PK]: {neq: idValue},
2453
- foo: 'val1',
2794
+ foo: modelData.foo,
2795
+ });
2796
+ return 0;
2797
+ }
2798
+ };
2799
+ await puv.validate(
2800
+ countMethod,
2801
+ 'replaceOrCreate',
2802
+ 'model',
2803
+ modelData,
2804
+ );
2805
+ expect(invoked).to.be.eql(2);
2806
+ });
2807
+
2808
+ it('skips uniqueness checking for an empty string', async function () {
2809
+ const dbs = new DatabaseSchema();
2810
+ dbs.defineModel({
2811
+ name: 'model',
2812
+ properties: {
2813
+ foo: {
2814
+ type: DataType.STRING,
2815
+ unique: PropertyUniqueness.SPARSE,
2816
+ },
2817
+ bar: {
2818
+ type: DataType.STRING,
2819
+ unique: PropertyUniqueness.SPARSE,
2820
+ },
2821
+ },
2822
+ });
2823
+ const puv = dbs.getService(PropertyUniquenessValidator);
2824
+ let invoked = 0;
2825
+ const idValue = 1;
2826
+ const modelData = {
2827
+ [DEF_PK]: idValue,
2828
+ foo: 'val1',
2829
+ bar: '',
2830
+ };
2831
+ const countMethod = where => {
2832
+ invoked++;
2833
+ if (invoked === 1) {
2834
+ expect(where).to.be.eql({[DEF_PK]: idValue});
2835
+ return 1;
2836
+ } else if (invoked === 2) {
2837
+ expect(where).to.be.eql({
2838
+ [DEF_PK]: {neq: idValue},
2839
+ foo: modelData.foo,
2840
+ });
2841
+ return 0;
2842
+ }
2843
+ };
2844
+ await puv.validate(
2845
+ countMethod,
2846
+ 'replaceOrCreate',
2847
+ 'model',
2848
+ modelData,
2849
+ );
2850
+ expect(invoked).to.be.eql(2);
2851
+ });
2852
+
2853
+ it('skips uniqueness checking for a zero number', async function () {
2854
+ const dbs = new DatabaseSchema();
2855
+ dbs.defineModel({
2856
+ name: 'model',
2857
+ properties: {
2858
+ foo: {
2859
+ type: DataType.NUMBER,
2860
+ unique: PropertyUniqueness.SPARSE,
2861
+ },
2862
+ bar: {
2863
+ type: DataType.NUMBER,
2864
+ unique: PropertyUniqueness.SPARSE,
2865
+ },
2866
+ },
2867
+ });
2868
+ const puv = dbs.getService(PropertyUniquenessValidator);
2869
+ let invoked = 0;
2870
+ const idValue = 1;
2871
+ const modelData = {
2872
+ [DEF_PK]: idValue,
2873
+ foo: 10,
2874
+ bar: 0,
2875
+ };
2876
+ const countMethod = where => {
2877
+ invoked++;
2878
+ if (invoked === 1) {
2879
+ expect(where).to.be.eql({[DEF_PK]: idValue});
2880
+ return 1;
2881
+ } else if (invoked === 2) {
2882
+ expect(where).to.be.eql({
2883
+ [DEF_PK]: {neq: idValue},
2884
+ foo: modelData.foo,
2885
+ });
2886
+ return 0;
2887
+ }
2888
+ };
2889
+ await puv.validate(
2890
+ countMethod,
2891
+ 'replaceOrCreate',
2892
+ 'model',
2893
+ modelData,
2894
+ );
2895
+ expect(invoked).to.be.eql(2);
2896
+ });
2897
+
2898
+ it('skips uniqueness checking for a false value', async function () {
2899
+ const dbs = new DatabaseSchema();
2900
+ dbs.defineModel({
2901
+ name: 'model',
2902
+ properties: {
2903
+ foo: {
2904
+ type: DataType.BOOLEAN,
2905
+ unique: PropertyUniqueness.SPARSE,
2906
+ },
2907
+ bar: {
2908
+ type: DataType.BOOLEAN,
2909
+ unique: PropertyUniqueness.SPARSE,
2910
+ },
2911
+ },
2912
+ });
2913
+ const puv = dbs.getService(PropertyUniquenessValidator);
2914
+ let invoked = 0;
2915
+ const idValue = 1;
2916
+ const modelData = {
2917
+ [DEF_PK]: idValue,
2918
+ foo: true,
2919
+ bar: false,
2920
+ };
2921
+ const countMethod = where => {
2922
+ invoked++;
2923
+ if (invoked === 1) {
2924
+ expect(where).to.be.eql({[DEF_PK]: idValue});
2925
+ return 1;
2926
+ } else if (invoked === 2) {
2927
+ expect(where).to.be.eql({
2928
+ [DEF_PK]: {neq: idValue},
2929
+ foo: modelData.foo,
2454
2930
  });
2455
2931
  return 0;
2456
2932
  }
@@ -2525,7 +3001,9 @@ describe('PropertyUniquenessValidator', function () {
2525
3001
  let invoked = 0;
2526
3002
  const modelData = {foo: 'val1', bar: 'val2'};
2527
3003
  const countMethod = where => {
2528
- if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
3004
+ if (invoked === 0) {
3005
+ expect(where).to.be.eql({foo: 'val1'});
3006
+ }
2529
3007
  invoked++;
2530
3008
  return 0;
2531
3009
  };
@@ -2558,7 +3036,7 @@ describe('PropertyUniquenessValidator', function () {
2558
3036
  await expect(promise2).not.to.be.rejected;
2559
3037
  });
2560
3038
 
2561
- it('skips uniqueness checking for blank values', async function () {
3039
+ it('skips uniqueness checking for an undefined value', async function () {
2562
3040
  const dbs = new DatabaseSchema();
2563
3041
  dbs.defineModel({
2564
3042
  name: 'model',
@@ -2574,13 +3052,99 @@ describe('PropertyUniquenessValidator', function () {
2574
3052
  },
2575
3053
  });
2576
3054
  const puv = dbs.getService(PropertyUniquenessValidator);
2577
- dbs
2578
- .getService(BlankValuesService)
2579
- .setBlankValuesOf(DataType.STRING, ['val2']);
2580
3055
  let invoked = 0;
2581
- const modelData = {foo: 'val1', bar: 'val2'};
3056
+ const modelData = {foo: 'val1', bar: undefined};
3057
+ const countMethod = where => {
3058
+ if (invoked === 0) {
3059
+ expect(where).to.be.eql({foo: modelData.foo});
3060
+ }
3061
+ invoked++;
3062
+ return 0;
3063
+ };
3064
+ await puv.validate(countMethod, 'patch', 'model', modelData);
3065
+ expect(invoked).to.be.eql(1);
3066
+ });
3067
+
3068
+ it('skips uniqueness checking for an empty string', async function () {
3069
+ const dbs = new DatabaseSchema();
3070
+ dbs.defineModel({
3071
+ name: 'model',
3072
+ properties: {
3073
+ foo: {
3074
+ type: DataType.STRING,
3075
+ unique: PropertyUniqueness.SPARSE,
3076
+ },
3077
+ bar: {
3078
+ type: DataType.STRING,
3079
+ unique: PropertyUniqueness.SPARSE,
3080
+ },
3081
+ },
3082
+ });
3083
+ const puv = dbs.getService(PropertyUniquenessValidator);
3084
+ let invoked = 0;
3085
+ const modelData = {foo: 'val1', bar: ''};
3086
+ const countMethod = where => {
3087
+ if (invoked === 0) {
3088
+ expect(where).to.be.eql({foo: modelData.foo});
3089
+ }
3090
+ invoked++;
3091
+ return 0;
3092
+ };
3093
+ await puv.validate(countMethod, 'patch', 'model', modelData);
3094
+ expect(invoked).to.be.eql(1);
3095
+ });
3096
+
3097
+ it('skips uniqueness checking for a zero number', async function () {
3098
+ const dbs = new DatabaseSchema();
3099
+ dbs.defineModel({
3100
+ name: 'model',
3101
+ properties: {
3102
+ foo: {
3103
+ type: DataType.NUMBER,
3104
+ unique: PropertyUniqueness.SPARSE,
3105
+ },
3106
+ bar: {
3107
+ type: DataType.NUMBER,
3108
+ unique: PropertyUniqueness.SPARSE,
3109
+ },
3110
+ },
3111
+ });
3112
+ const puv = dbs.getService(PropertyUniquenessValidator);
3113
+ let invoked = 0;
3114
+ const modelData = {foo: 10, bar: 0};
3115
+ const countMethod = where => {
3116
+ if (invoked === 0) {
3117
+ expect(where).to.be.eql({foo: modelData.foo});
3118
+ }
3119
+ invoked++;
3120
+ return 0;
3121
+ };
3122
+ await puv.validate(countMethod, 'patch', 'model', modelData);
3123
+ expect(invoked).to.be.eql(1);
3124
+ });
3125
+
3126
+ it('skips uniqueness checking for a false value', async function () {
3127
+ const dbs = new DatabaseSchema();
3128
+ dbs.defineModel({
3129
+ name: 'model',
3130
+ properties: {
3131
+ foo: {
3132
+ type: DataType.BOOLEAN,
3133
+ unique: PropertyUniqueness.SPARSE,
3134
+ },
3135
+ bar: {
3136
+ type: DataType.BOOLEAN,
3137
+ unique: PropertyUniqueness.SPARSE,
3138
+ },
3139
+ },
3140
+ });
3141
+ const puv = dbs.getService(PropertyUniquenessValidator);
3142
+ let invoked = 0;
3143
+ const modelData = {foo: true, bar: false};
2582
3144
  const countMethod = where => {
2583
- if (invoked === 0) expect(where).to.be.eql({foo: 'val1'});
3145
+ if (invoked === 0) {
3146
+ expect(where).to.be.eql({foo: modelData.foo});
3147
+ }
2584
3148
  invoked++;
2585
3149
  return 0;
2586
3150
  };
@@ -2654,11 +3218,12 @@ describe('PropertyUniquenessValidator', function () {
2654
3218
  const idValue = 1;
2655
3219
  const modelData = {foo: 'val1', bar: 'val2'};
2656
3220
  const countMethod = where => {
2657
- if (invoked === 0)
3221
+ if (invoked === 0) {
2658
3222
  expect(where).to.be.eql({
2659
3223
  [DEF_PK]: {neq: idValue},
2660
3224
  foo: 'val1',
2661
3225
  });
3226
+ }
2662
3227
  invoked++;
2663
3228
  return 0;
2664
3229
  };
@@ -2697,7 +3262,7 @@ describe('PropertyUniquenessValidator', function () {
2697
3262
  await expect(promise2).not.to.be.rejected;
2698
3263
  });
2699
3264
 
2700
- it('skips uniqueness checking for blank values', async function () {
3265
+ it('skips uniqueness checking for an undefined value', async function () {
2701
3266
  const dbs = new DatabaseSchema();
2702
3267
  dbs.defineModel({
2703
3268
  name: 'model',
@@ -2714,16 +3279,110 @@ describe('PropertyUniquenessValidator', function () {
2714
3279
  });
2715
3280
  const puv = dbs.getService(PropertyUniquenessValidator);
2716
3281
  let invoked = 0;
2717
- dbs
2718
- .getService(BlankValuesService)
2719
- .setBlankValuesOf(DataType.STRING, ['val2']);
2720
- const modelData = {foo: 'val1', bar: 'val2'};
3282
+ const modelData = {foo: 'val1', bar: undefined};
2721
3283
  const countMethod = where => {
2722
- if (invoked === 0)
3284
+ if (invoked === 0) {
2723
3285
  expect(where).to.be.eql({
2724
3286
  [DEF_PK]: {neq: 1},
2725
- foo: 'val1',
3287
+ foo: modelData.foo,
2726
3288
  });
3289
+ }
3290
+ invoked++;
3291
+ return 0;
3292
+ };
3293
+ await puv.validate(countMethod, 'patchById', 'model', modelData, 1);
3294
+ expect(invoked).to.be.eql(1);
3295
+ });
3296
+
3297
+ it('skips uniqueness checking for an empty string', async function () {
3298
+ const dbs = new DatabaseSchema();
3299
+ dbs.defineModel({
3300
+ name: 'model',
3301
+ properties: {
3302
+ foo: {
3303
+ type: DataType.STRING,
3304
+ unique: PropertyUniqueness.SPARSE,
3305
+ },
3306
+ bar: {
3307
+ type: DataType.STRING,
3308
+ unique: PropertyUniqueness.SPARSE,
3309
+ },
3310
+ },
3311
+ });
3312
+ const puv = dbs.getService(PropertyUniquenessValidator);
3313
+ let invoked = 0;
3314
+ const modelData = {foo: 'val1', bar: ''};
3315
+ const countMethod = where => {
3316
+ if (invoked === 0) {
3317
+ expect(where).to.be.eql({
3318
+ [DEF_PK]: {neq: 1},
3319
+ foo: modelData.foo,
3320
+ });
3321
+ }
3322
+ invoked++;
3323
+ return 0;
3324
+ };
3325
+ await puv.validate(countMethod, 'patchById', 'model', modelData, 1);
3326
+ expect(invoked).to.be.eql(1);
3327
+ });
3328
+
3329
+ it('skips uniqueness checking for a zero number', async function () {
3330
+ const dbs = new DatabaseSchema();
3331
+ dbs.defineModel({
3332
+ name: 'model',
3333
+ properties: {
3334
+ foo: {
3335
+ type: DataType.NUMBER,
3336
+ unique: PropertyUniqueness.SPARSE,
3337
+ },
3338
+ bar: {
3339
+ type: DataType.NUMBER,
3340
+ unique: PropertyUniqueness.SPARSE,
3341
+ },
3342
+ },
3343
+ });
3344
+ const puv = dbs.getService(PropertyUniquenessValidator);
3345
+ let invoked = 0;
3346
+ const modelData = {foo: 10, bar: 0};
3347
+ const countMethod = where => {
3348
+ if (invoked === 0) {
3349
+ expect(where).to.be.eql({
3350
+ [DEF_PK]: {neq: 1},
3351
+ foo: modelData.foo,
3352
+ });
3353
+ }
3354
+ invoked++;
3355
+ return 0;
3356
+ };
3357
+ await puv.validate(countMethod, 'patchById', 'model', modelData, 1);
3358
+ expect(invoked).to.be.eql(1);
3359
+ });
3360
+
3361
+ it('skips uniqueness checking for a false value', async function () {
3362
+ const dbs = new DatabaseSchema();
3363
+ dbs.defineModel({
3364
+ name: 'model',
3365
+ properties: {
3366
+ foo: {
3367
+ type: DataType.BOOLEAN,
3368
+ unique: PropertyUniqueness.SPARSE,
3369
+ },
3370
+ bar: {
3371
+ type: DataType.BOOLEAN,
3372
+ unique: PropertyUniqueness.SPARSE,
3373
+ },
3374
+ },
3375
+ });
3376
+ const puv = dbs.getService(PropertyUniquenessValidator);
3377
+ let invoked = 0;
3378
+ const modelData = {foo: true, bar: false};
3379
+ const countMethod = where => {
3380
+ if (invoked === 0) {
3381
+ expect(where).to.be.eql({
3382
+ [DEF_PK]: {neq: 1},
3383
+ foo: modelData.foo,
3384
+ });
3385
+ }
2727
3386
  invoked++;
2728
3387
  return 0;
2729
3388
  };
@@ -2751,11 +3410,12 @@ describe('PropertyUniquenessValidator', function () {
2751
3410
  const idValue = 1;
2752
3411
  const modelData = {foo: 'bar'};
2753
3412
  const countMethod = where => {
2754
- if (invoked === 0)
3413
+ if (invoked === 0) {
2755
3414
  expect(where).to.be.eql({
2756
3415
  myId: {neq: idValue},
2757
3416
  foo: 'bar',
2758
3417
  });
3418
+ }
2759
3419
  invoked++;
2760
3420
  return 0;
2761
3421
  };