@e22m4u/js-repository-mongodb-adapter 0.0.24 → 0.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-repository-mongodb-adapter",
3
- "version": "0.0.24",
3
+ "version": "0.1.0",
4
4
  "description": "MongoDB адаптер для @e22m4u/js-repository",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -33,27 +33,27 @@
33
33
  "license": "MIT",
34
34
  "homepage": "https://github.com/e22m4u/js-repository-mongodb-adapter",
35
35
  "dependencies": {
36
- "mongodb": "5.8.1"
36
+ "mongodb": "5.9.2"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@e22m4u/js-format": "*",
40
40
  "@e22m4u/js-service": "*",
41
- "@e22m4u/js-repository": "~0.0.41"
41
+ "@e22m4u/js-repository": "~0.1.0"
42
42
  },
43
43
  "devDependencies": {
44
- "@commitlint/cli": "^17.8.0",
45
- "@commitlint/config-conventional": "^17.8.0",
44
+ "@commitlint/cli": "^18.4.3",
45
+ "@commitlint/config-conventional": "^18.4.3",
46
46
  "c8": "^8.0.1",
47
47
  "chai": "^4.3.10",
48
48
  "chai-as-promised": "^7.1.1",
49
- "chai-spies": "^1.0.0",
49
+ "chai-spies": "^1.1.0",
50
50
  "dotenv": "^16.3.1",
51
- "eslint": "^8.51.0",
52
- "eslint-config-prettier": "^9.0.0",
51
+ "eslint": "^8.56.0",
52
+ "eslint-config-prettier": "^9.1.0",
53
53
  "eslint-plugin-chai-expect": "^3.0.0",
54
54
  "eslint-plugin-mocha": "^10.2.0",
55
55
  "husky": "^8.0.3",
56
56
  "mocha": "^10.2.0",
57
- "prettier": "^3.0.3"
57
+ "prettier": "^3.1.1"
58
58
  }
59
59
  }
@@ -601,7 +601,7 @@ export class MongodbAdapter extends Adapter {
601
601
  async create(modelName, modelData, filter = undefined) {
602
602
  const idPropName = this._getIdPropName(modelName);
603
603
  const idValue = modelData[idPropName];
604
- if (idValue == null) {
604
+ if (idValue == null || idValue === '') {
605
605
  const pkType = this._getIdType(modelName);
606
606
  if (pkType !== DataType.STRING && pkType !== DataType.ANY)
607
607
  throw new InvalidArgumentError(
@@ -650,6 +650,50 @@ export class MongodbAdapter extends Adapter {
650
650
  return this._fromDatabase(modelName, replacedData);
651
651
  }
652
652
 
653
+ /**
654
+ * Replace or create.
655
+ *
656
+ * @param {string} modelName
657
+ * @param {object} modelData
658
+ * @param {object|undefined} filter
659
+ * @return {Promise<object>}
660
+ */
661
+ async replaceOrCreate(modelName, modelData, filter = undefined) {
662
+ const idPropName = this._getIdPropName(modelName);
663
+ let idValue = modelData[idPropName];
664
+ idValue = this._coerceId(idValue);
665
+ if (idValue == null || idValue === '') {
666
+ const pkType = this._getIdType(modelName);
667
+ if (pkType !== DataType.STRING && pkType !== DataType.ANY)
668
+ throw new InvalidArgumentError(
669
+ 'MongoDB unable to generate primary keys of %s. ' +
670
+ 'Do provide your own value for the %v property ' +
671
+ 'or set property type to String.',
672
+ capitalize(pkType),
673
+ idPropName,
674
+ );
675
+ delete modelData[idPropName];
676
+ idValue = undefined;
677
+ }
678
+ const tableData = this._toDatabase(modelName, modelData);
679
+ const table = this._getCollection(modelName);
680
+ if (idValue == null) {
681
+ const {insertedId} = await table.insertOne(tableData);
682
+ idValue = insertedId;
683
+ } else {
684
+ const {upsertedId} = await table.replaceOne({_id: idValue}, tableData, {
685
+ upsert: true,
686
+ });
687
+ if (upsertedId) idValue = upsertedId;
688
+ }
689
+ const projection = this._buildProjection(
690
+ modelName,
691
+ filter && filter.fields,
692
+ );
693
+ const upsertedData = await table.findOne({_id: idValue}, {projection});
694
+ return this._fromDatabase(modelName, upsertedData);
695
+ }
696
+
653
697
  /**
654
698
  * Patch.
655
699
  *
@@ -1083,6 +1083,16 @@ describe('MongodbAdapter', function () {
1083
1083
  expect(result[DEF_PK]).to.have.lengthOf(24);
1084
1084
  });
1085
1085
 
1086
+ it('generates a new identifier when a value of a primary key is an empty string', async function () {
1087
+ const schema = createSchema();
1088
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
1089
+ const rep = schema.getRepository('model');
1090
+ const result = await rep.create({[DEF_PK]: '', foo: 'bar'});
1091
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
1092
+ expect(typeof result[DEF_PK]).to.be.eq('string');
1093
+ expect(result[DEF_PK]).to.have.lengthOf(24);
1094
+ });
1095
+
1086
1096
  it('generates a new identifier for a primary key of a "string" type', async function () {
1087
1097
  const schema = createSchema();
1088
1098
  schema.defineModel({
@@ -1977,6 +1987,580 @@ describe('MongodbAdapter', function () {
1977
1987
  });
1978
1988
  });
1979
1989
 
1990
+ describe('replaceOrCreate', function () {
1991
+ it('generates a new identifier when a value of a primary key is not provided', async function () {
1992
+ const schema = createSchema();
1993
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
1994
+ const rep = schema.getRepository('model');
1995
+ const result = await rep.replaceOrCreate({foo: 'bar'});
1996
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
1997
+ expect(typeof result[DEF_PK]).to.be.eq('string');
1998
+ expect(result[DEF_PK]).to.have.lengthOf(24);
1999
+ });
2000
+
2001
+ it('generates a new identifier when a value of a primary key is undefined', async function () {
2002
+ const schema = createSchema();
2003
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2004
+ const rep = schema.getRepository('model');
2005
+ const result = await rep.replaceOrCreate({
2006
+ [DEF_PK]: undefined,
2007
+ foo: 'bar',
2008
+ });
2009
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
2010
+ expect(typeof result[DEF_PK]).to.be.eq('string');
2011
+ expect(result[DEF_PK]).to.have.lengthOf(24);
2012
+ });
2013
+
2014
+ it('generates a new identifier when a value of a primary key is null', async function () {
2015
+ const schema = createSchema();
2016
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2017
+ const rep = schema.getRepository('model');
2018
+ const result = await rep.replaceOrCreate({[DEF_PK]: null, foo: 'bar'});
2019
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
2020
+ expect(typeof result[DEF_PK]).to.be.eq('string');
2021
+ expect(result[DEF_PK]).to.have.lengthOf(24);
2022
+ });
2023
+
2024
+ it('generates a new identifier when a value of a primary key is an empty string', async function () {
2025
+ const schema = createSchema();
2026
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2027
+ const rep = schema.getRepository('model');
2028
+ const result = await rep.replaceOrCreate({[DEF_PK]: '', foo: 'bar'});
2029
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
2030
+ expect(typeof result[DEF_PK]).to.be.eq('string');
2031
+ expect(result[DEF_PK]).to.have.lengthOf(24);
2032
+ });
2033
+
2034
+ it('generates a new identifier for a primary key of a "string" type', async function () {
2035
+ const schema = createSchema();
2036
+ schema.defineModel({
2037
+ name: 'model',
2038
+ datasource: 'mongodb',
2039
+ properties: {
2040
+ id: {
2041
+ type: DataType.STRING,
2042
+ primaryKey: true,
2043
+ },
2044
+ },
2045
+ });
2046
+ const rep = schema.getRepository('model');
2047
+ const result = await rep.replaceOrCreate({[DEF_PK]: null, foo: 'bar'});
2048
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
2049
+ expect(typeof result[DEF_PK]).to.be.eq('string');
2050
+ expect(result[DEF_PK]).to.have.lengthOf(24);
2051
+ });
2052
+
2053
+ it('generates a new identifier for a primary key of a "any" type', async function () {
2054
+ const schema = createSchema();
2055
+ schema.defineModel({
2056
+ name: 'model',
2057
+ datasource: 'mongodb',
2058
+ properties: {
2059
+ id: {
2060
+ type: DataType.ANY,
2061
+ primaryKey: true,
2062
+ },
2063
+ },
2064
+ });
2065
+ const rep = schema.getRepository('model');
2066
+ const result = await rep.replaceOrCreate({[DEF_PK]: null, foo: 'bar'});
2067
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
2068
+ expect(typeof result[DEF_PK]).to.be.eq('string');
2069
+ expect(result[DEF_PK]).to.have.lengthOf(24);
2070
+ });
2071
+
2072
+ it('throws an error when generating a new value for a primary key of a "number" type', async function () {
2073
+ const schema = createSchema();
2074
+ schema.defineModel({
2075
+ name: 'model',
2076
+ datasource: 'mongodb',
2077
+ properties: {
2078
+ id: {
2079
+ type: DataType.NUMBER,
2080
+ primaryKey: true,
2081
+ },
2082
+ },
2083
+ });
2084
+ const rep = schema.getRepository('model');
2085
+ const promise = rep.replaceOrCreate({});
2086
+ expect(promise).to.be.rejectedWith(
2087
+ 'MongoDB unable to generate primary keys of Number. ' +
2088
+ 'Do provide your own value for the "id" property ' +
2089
+ 'or set the property type to String.',
2090
+ );
2091
+ });
2092
+
2093
+ it('throws an error when generating a new value for a primary key of a "boolean" type', async function () {
2094
+ const schema = createSchema();
2095
+ schema.defineModel({
2096
+ name: 'model',
2097
+ datasource: 'mongodb',
2098
+ properties: {
2099
+ id: {
2100
+ type: DataType.BOOLEAN,
2101
+ primaryKey: true,
2102
+ },
2103
+ },
2104
+ });
2105
+ const rep = schema.getRepository('model');
2106
+ const promise = rep.replaceOrCreate({});
2107
+ expect(promise).to.be.rejectedWith(
2108
+ 'MongoDB unable to generate primary keys of Boolean. ' +
2109
+ 'Do provide your own value for the "id" property ' +
2110
+ 'or set the property type to String.',
2111
+ );
2112
+ });
2113
+
2114
+ it('throws an error when generating a new value for a primary key of a "array" type', async function () {
2115
+ const schema = createSchema();
2116
+ schema.defineModel({
2117
+ name: 'model',
2118
+ datasource: 'mongodb',
2119
+ properties: {
2120
+ id: {
2121
+ type: DataType.ARRAY,
2122
+ primaryKey: true,
2123
+ },
2124
+ },
2125
+ });
2126
+ const rep = schema.getRepository('model');
2127
+ const promise = rep.replaceOrCreate({});
2128
+ expect(promise).to.be.rejectedWith(
2129
+ 'MongoDB unable to generate primary keys of Array. ' +
2130
+ 'Do provide your own value for the "id" property ' +
2131
+ 'or set the property type to String.',
2132
+ );
2133
+ });
2134
+
2135
+ it('throws an error when generating a new value for a primary key of a "object" type', async function () {
2136
+ const schema = createSchema();
2137
+ schema.defineModel({
2138
+ name: 'model',
2139
+ datasource: 'mongodb',
2140
+ properties: {
2141
+ id: {
2142
+ type: DataType.OBJECT,
2143
+ primaryKey: true,
2144
+ },
2145
+ },
2146
+ });
2147
+ const rep = schema.getRepository('model');
2148
+ const promise = rep.replaceOrCreate({});
2149
+ expect(promise).to.be.rejectedWith(
2150
+ 'MongoDB unable to generate primary keys of Object. ' +
2151
+ 'Do provide your own value for the "id" property ' +
2152
+ 'or set the property type to String.',
2153
+ );
2154
+ });
2155
+
2156
+ it('allows to specify an ObjectID instance for a default primary key', async function () {
2157
+ const schema = createSchema();
2158
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2159
+ const rep = schema.getRepository('model');
2160
+ const oid = new ObjectId();
2161
+ const result = await rep.replaceOrCreate({[DEF_PK]: oid});
2162
+ expect(result).to.be.eql({[DEF_PK]: String(oid)});
2163
+ const rawData = await MDB_CLIENT.db()
2164
+ .collection('model')
2165
+ .findOne({_id: oid});
2166
+ expect(rawData).to.be.not.null;
2167
+ });
2168
+
2169
+ it('allows to specify an ObjectID string for a default primary key', async function () {
2170
+ const schema = createSchema();
2171
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2172
+ const rep = schema.getRepository('model');
2173
+ const oid = new ObjectId();
2174
+ const id = String(oid);
2175
+ const result = await rep.replaceOrCreate({[DEF_PK]: id});
2176
+ expect(result).to.be.eql({[DEF_PK]: id});
2177
+ const rawData = await MDB_CLIENT.db()
2178
+ .collection('model')
2179
+ .findOne({_id: oid});
2180
+ expect(rawData).to.be.not.null;
2181
+ });
2182
+
2183
+ it('allows to specify an ObjectID instance for "id" primary key', async function () {
2184
+ const schema = createSchema();
2185
+ schema.defineModel({
2186
+ name: 'model',
2187
+ datasource: 'mongodb',
2188
+ properties: {
2189
+ id: {
2190
+ type: DataType.ANY,
2191
+ primaryKey: true,
2192
+ },
2193
+ },
2194
+ });
2195
+ const rep = schema.getRepository('model');
2196
+ const oid = new ObjectId();
2197
+ const result = await rep.replaceOrCreate({id: oid});
2198
+ expect(result).to.be.eql({id: String(oid)});
2199
+ const rawData = await MDB_CLIENT.db()
2200
+ .collection('model')
2201
+ .findOne({_id: oid});
2202
+ expect(rawData).to.be.not.null;
2203
+ });
2204
+
2205
+ it('allows to specify an ObjectID string for "id" primary key', async function () {
2206
+ const schema = createSchema();
2207
+ schema.defineModel({
2208
+ name: 'model',
2209
+ datasource: 'mongodb',
2210
+ properties: {
2211
+ id: {
2212
+ type: DataType.STRING,
2213
+ primaryKey: true,
2214
+ },
2215
+ },
2216
+ });
2217
+ const rep = schema.getRepository('model');
2218
+ const oid = new ObjectId();
2219
+ const id = String(oid);
2220
+ const result = await rep.replaceOrCreate({id});
2221
+ expect(result).to.be.eql({id});
2222
+ const rawData = await MDB_CLIENT.db()
2223
+ .collection('model')
2224
+ .findOne({_id: oid});
2225
+ expect(rawData).to.be.not.null;
2226
+ });
2227
+
2228
+ it('allows to specify an ObjectID instance for "_id" primary key', async function () {
2229
+ const schema = createSchema();
2230
+ schema.defineModel({
2231
+ name: 'model',
2232
+ datasource: 'mongodb',
2233
+ properties: {
2234
+ _id: {
2235
+ type: DataType.ANY,
2236
+ primaryKey: true,
2237
+ },
2238
+ },
2239
+ });
2240
+ const rep = schema.getRepository('model');
2241
+ const oid = new ObjectId();
2242
+ const result = await rep.replaceOrCreate({_id: oid});
2243
+ expect(result).to.be.eql({_id: String(oid)});
2244
+ const rawData = await MDB_CLIENT.db()
2245
+ .collection('model')
2246
+ .findOne({_id: oid});
2247
+ expect(rawData).to.be.not.null;
2248
+ });
2249
+
2250
+ it('allows to specify an ObjectID string for "_id" primary key', async function () {
2251
+ const schema = createSchema();
2252
+ schema.defineModel({
2253
+ name: 'model',
2254
+ datasource: 'mongodb',
2255
+ properties: {
2256
+ _id: {
2257
+ type: DataType.STRING,
2258
+ primaryKey: true,
2259
+ },
2260
+ },
2261
+ });
2262
+ const rep = schema.getRepository('model');
2263
+ const oid = new ObjectId();
2264
+ const id = String(oid);
2265
+ const result = await rep.replaceOrCreate({_id: id});
2266
+ expect(result).to.be.eql({_id: id});
2267
+ const rawData = await MDB_CLIENT.db()
2268
+ .collection('model')
2269
+ .findOne({_id: oid});
2270
+ expect(rawData).to.be.not.null;
2271
+ });
2272
+
2273
+ it('throws an error for a custom primary key', async function () {
2274
+ const schema = createSchema();
2275
+ schema.defineModel({
2276
+ name: 'model',
2277
+ datasource: 'mongodb',
2278
+ properties: {
2279
+ myId: {
2280
+ type: DataType.ANY,
2281
+ primaryKey: true,
2282
+ },
2283
+ },
2284
+ });
2285
+ const rep = schema.getRepository('model');
2286
+ const oid = new ObjectId();
2287
+ const promise = rep.replaceOrCreate({myId: oid});
2288
+ await expect(promise).to.be.rejectedWith(
2289
+ 'MongoDB is not supporting custom names of the primary key. ' +
2290
+ 'Do use "id" as a primary key instead of "myId".',
2291
+ );
2292
+ });
2293
+
2294
+ it('uses a specified column name for a regular property', async function () {
2295
+ const schema = createSchema();
2296
+ schema.defineModel({
2297
+ name: 'model',
2298
+ datasource: 'mongodb',
2299
+ properties: {
2300
+ foo: {
2301
+ type: DataType.NUMBER,
2302
+ columnName: 'bar',
2303
+ },
2304
+ },
2305
+ });
2306
+ const rep = schema.getRepository('model');
2307
+ const result = await rep.replaceOrCreate({foo: 10});
2308
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10});
2309
+ const oid = new ObjectId(result[DEF_PK]);
2310
+ const rawData = await MDB_CLIENT.db()
2311
+ .collection('model')
2312
+ .findOne({_id: oid});
2313
+ expect(rawData).to.be.eql({_id: oid, bar: 10});
2314
+ });
2315
+
2316
+ it('uses a specified column name for a regular property with a default value', async function () {
2317
+ const schema = createSchema();
2318
+ schema.defineModel({
2319
+ name: 'model',
2320
+ datasource: 'mongodb',
2321
+ properties: {
2322
+ foo: {
2323
+ type: DataType.NUMBER,
2324
+ columnName: 'bar',
2325
+ default: 10,
2326
+ },
2327
+ },
2328
+ });
2329
+ const rep = schema.getRepository('model');
2330
+ const result = await rep.replaceOrCreate({});
2331
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10});
2332
+ const oid = new ObjectId(result[DEF_PK]);
2333
+ const rawData = await MDB_CLIENT.db()
2334
+ .collection('model')
2335
+ .findOne({_id: oid});
2336
+ expect(rawData).to.be.eql({_id: oid, bar: 10});
2337
+ });
2338
+
2339
+ it('stores a Date instance as date and returns string type', async function () {
2340
+ const schema = createSchema();
2341
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2342
+ const rep = schema.getRepository('model');
2343
+ const date = new Date();
2344
+ const dateString = date.toISOString();
2345
+ const result = await rep.replaceOrCreate({date});
2346
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], date: dateString});
2347
+ const oid = new ObjectId(result[DEF_PK]);
2348
+ const rawData = await MDB_CLIENT.db()
2349
+ .collection('model')
2350
+ .findOne({_id: oid});
2351
+ expect(rawData).to.be.eql({_id: oid, date});
2352
+ });
2353
+
2354
+ it('stores a Date string as date and returns string type', async function () {
2355
+ const schema = createSchema();
2356
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2357
+ const rep = schema.getRepository('model');
2358
+ const date = new Date();
2359
+ const dateString = date.toISOString();
2360
+ const result = await rep.replaceOrCreate({date: dateString});
2361
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], date: dateString});
2362
+ const oid = new ObjectId(result[DEF_PK]);
2363
+ const rawData = await MDB_CLIENT.db()
2364
+ .collection('model')
2365
+ .findOne({_id: oid});
2366
+ expect(rawData).to.be.eql({_id: oid, date});
2367
+ });
2368
+
2369
+ it('stores a string as is', async function () {
2370
+ const schema = createSchema();
2371
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2372
+ const rep = schema.getRepository('model');
2373
+ const result = await rep.replaceOrCreate({foo: 'str'});
2374
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'str'});
2375
+ const oid = new ObjectId(result[DEF_PK]);
2376
+ const rawData = await MDB_CLIENT.db()
2377
+ .collection('model')
2378
+ .findOne({_id: oid});
2379
+ expect(rawData).to.be.eql({_id: oid, foo: 'str'});
2380
+ });
2381
+
2382
+ it('stores a number as is', async function () {
2383
+ const schema = createSchema();
2384
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2385
+ const rep = schema.getRepository('model');
2386
+ const result = await rep.replaceOrCreate({foo: 10});
2387
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10});
2388
+ const oid = new ObjectId(result[DEF_PK]);
2389
+ const rawData = await MDB_CLIENT.db()
2390
+ .collection('model')
2391
+ .findOne({_id: oid});
2392
+ expect(rawData).to.be.eql({_id: oid, foo: 10});
2393
+ });
2394
+
2395
+ it('stores a boolean as is', async function () {
2396
+ const schema = createSchema();
2397
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2398
+ const rep = schema.getRepository('model');
2399
+ const result = await rep.replaceOrCreate({foo: true, bar: false});
2400
+ expect(result).to.be.eql({
2401
+ [DEF_PK]: result[DEF_PK],
2402
+ foo: true,
2403
+ bar: false,
2404
+ });
2405
+ const oid = new ObjectId(result[DEF_PK]);
2406
+ const rawData = await MDB_CLIENT.db()
2407
+ .collection('model')
2408
+ .findOne({_id: oid});
2409
+ expect(rawData).to.be.eql({_id: oid, foo: true, bar: false});
2410
+ });
2411
+
2412
+ it('stores an array as is', async function () {
2413
+ const schema = createSchema();
2414
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2415
+ const rep = schema.getRepository('model');
2416
+ const result = await rep.replaceOrCreate({foo: ['bar']});
2417
+ expect(result).to.be.eql({
2418
+ [DEF_PK]: result[DEF_PK],
2419
+ foo: ['bar'],
2420
+ });
2421
+ const oid = new ObjectId(result[DEF_PK]);
2422
+ const rawData = await MDB_CLIENT.db()
2423
+ .collection('model')
2424
+ .findOne({_id: oid});
2425
+ expect(rawData).to.be.eql({_id: oid, foo: ['bar']});
2426
+ });
2427
+
2428
+ it('stores an object as is', async function () {
2429
+ const schema = createSchema();
2430
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2431
+ const rep = schema.getRepository('model');
2432
+ const result = await rep.replaceOrCreate({foo: {bar: 10}});
2433
+ expect(result).to.be.eql({
2434
+ [DEF_PK]: result[DEF_PK],
2435
+ foo: {bar: 10},
2436
+ });
2437
+ const oid = new ObjectId(result[DEF_PK]);
2438
+ const rawData = await MDB_CLIENT.db()
2439
+ .collection('model')
2440
+ .findOne({_id: oid});
2441
+ expect(rawData).to.be.eql({_id: oid, foo: {bar: 10}});
2442
+ });
2443
+
2444
+ it('stores an undefined as null', async function () {
2445
+ const schema = createSchema();
2446
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2447
+ const rep = schema.getRepository('model');
2448
+ const result = await rep.replaceOrCreate({foo: undefined});
2449
+ expect(result).to.be.eql({
2450
+ [DEF_PK]: result[DEF_PK],
2451
+ foo: null,
2452
+ });
2453
+ const oid = new ObjectId(result[DEF_PK]);
2454
+ const rawData = await MDB_CLIENT.db()
2455
+ .collection('model')
2456
+ .findOne({_id: oid});
2457
+ expect(rawData).to.be.eql({_id: oid, foo: null});
2458
+ });
2459
+
2460
+ it('stores an null as is', async function () {
2461
+ const schema = createSchema();
2462
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2463
+ const rep = schema.getRepository('model');
2464
+ const result = await rep.replaceOrCreate({foo: null});
2465
+ expect(result).to.be.eql({
2466
+ [DEF_PK]: result[DEF_PK],
2467
+ foo: null,
2468
+ });
2469
+ const oid = new ObjectId(result[DEF_PK]);
2470
+ const rawData = await MDB_CLIENT.db()
2471
+ .collection('model')
2472
+ .findOne({_id: oid});
2473
+ expect(rawData).to.be.eql({_id: oid, foo: null});
2474
+ });
2475
+
2476
+ it('uses a short fields clause to filter results', async function () {
2477
+ const schema = createSchema();
2478
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2479
+ const rep = schema.getRepository('model');
2480
+ const result = await rep.replaceOrCreate(
2481
+ {foo: 10, bar: 20},
2482
+ {fields: 'foo'},
2483
+ );
2484
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10});
2485
+ });
2486
+
2487
+ it('uses a full fields clause to filter results', async function () {
2488
+ const schema = createSchema();
2489
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2490
+ const rep = schema.getRepository('model');
2491
+ const result = await rep.replaceOrCreate(
2492
+ {foo: 10, bar: 20, baz: 30},
2493
+ {fields: ['foo', 'bar']},
2494
+ );
2495
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10, bar: 20});
2496
+ const oid = new ObjectId(result[DEF_PK]);
2497
+ const rawData = await MDB_CLIENT.db()
2498
+ .collection('model')
2499
+ .findOne({_id: oid});
2500
+ expect(rawData).to.be.eql({_id: oid, foo: 10, bar: 20, baz: 30});
2501
+ });
2502
+
2503
+ it('a fields clause uses property names instead of column names', async function () {
2504
+ const schema = createSchema();
2505
+ schema.defineModel({
2506
+ name: 'model',
2507
+ datasource: 'mongodb',
2508
+ properties: {
2509
+ foo: {
2510
+ type: DataType.NUMBER,
2511
+ columnName: 'fooCol',
2512
+ },
2513
+ bar: {
2514
+ type: DataType.NUMBER,
2515
+ columnName: 'barCol',
2516
+ },
2517
+ baz: {
2518
+ type: DataType.NUMBER,
2519
+ columnName: 'bazCol',
2520
+ },
2521
+ },
2522
+ });
2523
+ const rep = schema.getRepository('model');
2524
+ const result = await rep.replaceOrCreate(
2525
+ {foo: 10, bar: 20, baz: 30},
2526
+ {fields: ['fooCol', 'barCol']},
2527
+ );
2528
+ expect(result).to.be.eql({[DEF_PK]: result[DEF_PK]});
2529
+ });
2530
+
2531
+ it('removes properties when replacing an item by a given identifier', async function () {
2532
+ const schema = createSchema();
2533
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2534
+ const rep = schema.getRepository('model');
2535
+ const created = await rep.create({foo: 10});
2536
+ const id = created[DEF_PK];
2537
+ const replacer = {[DEF_PK]: id, bar: 20};
2538
+ const replaced = await rep.replaceOrCreate(replacer);
2539
+ expect(replaced).to.be.eql(replacer);
2540
+ const oid = new ObjectId(id);
2541
+ const rawData = await MDB_CLIENT.db()
2542
+ .collection('model')
2543
+ .findOne({_id: oid});
2544
+ expect(rawData).to.be.eql({_id: oid, bar: 20});
2545
+ });
2546
+
2547
+ it('does not throws an error if nothing changed', async function () {
2548
+ const schema = createSchema();
2549
+ schema.defineModel({name: 'model', datasource: 'mongodb'});
2550
+ const rep = schema.getRepository('model');
2551
+ const created = await rep.create({foo: 10});
2552
+ const id = created[DEF_PK];
2553
+ const replacer = {[DEF_PK]: id, foo: 10};
2554
+ const replaced = await rep.replaceOrCreate(replacer);
2555
+ expect(replaced).to.be.eql(replacer);
2556
+ const oid = new ObjectId(id);
2557
+ const rawData = await MDB_CLIENT.db()
2558
+ .collection('model')
2559
+ .findOne({_id: oid});
2560
+ expect(rawData).to.be.eql({_id: oid, foo: 10});
2561
+ });
2562
+ });
2563
+
1980
2564
  describe('patch', function () {
1981
2565
  it('updates only provided properties for all items and returns their number', async function () {
1982
2566
  const schema = createSchema();