@bedrockio/model 0.2.0 → 0.2.2

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/README.md CHANGED
@@ -436,8 +436,7 @@ validation which will:
436
436
  - Append the same validation to `Model.getCreateSchema` and
437
437
  `Model.getUpdateSchema` to allow this constraint to trickle down to the API.
438
438
 
439
- > :warning: updateOne and updateMany
440
- >
439
+ > [!WARNING]
441
440
  > Note that calling `Model.updateOne` will throw an error when a unique field
442
441
  > exists on any document **including the document being updated**. This is an
443
442
  > intentional constraint that allows `updateOne` better peformance by not having
@@ -951,7 +950,7 @@ is set after verification:
951
950
  A user is allowed to update the name of their own shop and admins can as well.
952
951
  However, only admins can set the owner of the shop:
953
952
 
954
- ```json
953
+ ```jsonc
955
954
  // shop.json
956
955
  {
957
956
  "name": {
@@ -1010,7 +1009,7 @@ check the document is the same as `authUser`.
1010
1009
  Delete hooks are a powerful way to define what actions are taken on document
1011
1010
  deletion. They are defined in the `onDelete` field of the model definition file:
1012
1011
 
1013
- ```json
1012
+ ```jsonc
1014
1013
  // user.json
1015
1014
  {
1016
1015
  "attributes": {
@@ -1026,7 +1025,7 @@ deletion. They are defined in the `onDelete` field of the model definition file:
1026
1025
  "foreign": {
1027
1026
  Shop: "owner"
1028
1027
  },
1029
- }
1028
+ },
1030
1029
  "errorOnReferenced": {
1031
1030
  "except": ["AuditEntry"]
1032
1031
  }
@@ -1094,7 +1093,7 @@ Models that have delete hooks defined on them will keep a reference of the
1094
1093
  documents that were deleted. Calling `.restore()` on the document will also
1095
1094
  restore these references.
1096
1095
 
1097
- > [!IMPORTANT]
1096
+ > [!WARNING]
1098
1097
  > Delete hooks are **only** run on a single document (`.delete` or `.restore`).
1099
1098
  > They will not be run when using model methods like `deleteOne` or
1100
1099
  > `deleteMany`.
@@ -142,9 +142,6 @@ function attributesToMongoose(attributes) {
142
142
  return definition;
143
143
  }
144
144
  function assertSchemaType(type, path) {
145
- if (type === 'Mixed') {
146
- throw new Error('Type "Mixed" is not allowed. Use "Object" instead.');
147
- }
148
145
  if (typeof type === 'string') {
149
146
  if (!isMongooseType(type)) {
150
147
  const p = path.join('.');
@@ -6,8 +6,10 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.applySoftDelete = applySoftDelete;
7
7
  exports.assertUnique = assertUnique;
8
8
  exports.hasUniqueConstraints = hasUniqueConstraints;
9
+ var _mongoose = _interopRequireDefault(require("mongoose"));
9
10
  var _lodash = require("lodash");
10
11
  var _query = require("./query");
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
13
  function applySoftDelete(schema) {
12
14
  applyQueries(schema);
13
15
  applyUniqueConstraints(schema);
@@ -219,7 +221,7 @@ function applyUniqueConstraints(schema) {
219
221
  return;
220
222
  }
221
223
  schema.pre('save', async function () {
222
- await assertUnique(this.toObject(), {
224
+ await assertUnique(this, {
223
225
  operation: this.isNew ? 'create' : 'update',
224
226
  model: this.constructor,
225
227
  schema
@@ -340,6 +342,11 @@ function resolveUnique(schema, obj, map = {}, path = []) {
340
342
  for (let el of obj) {
341
343
  resolveUnique(schema, el, map, path);
342
344
  }
345
+ } else if (obj instanceof _mongoose.default.Document) {
346
+ obj.schema.eachPath(key => {
347
+ const val = obj.get(key);
348
+ resolveUnique(schema, val, map, [...path, key]);
349
+ });
343
350
  } else if (obj && typeof obj === 'object') {
344
351
  for (let [key, val] of Object.entries(obj)) {
345
352
  resolveUnique(schema, val, map, [...path, key]);
@@ -315,11 +315,12 @@ function getSchemaForType(type, options) {
315
315
  return _yada.default.boolean();
316
316
  case 'Date':
317
317
  return _yada.default.date().iso().tag(DATE_TAGS);
318
- case 'Mixed':
319
318
  case 'Object':
320
319
  return _yada.default.object();
321
320
  case 'Array':
322
321
  return _yada.default.array();
322
+ case 'Mixed':
323
+ return _yada.default.any();
323
324
  case 'ObjectId':
324
325
  if (options.allowExpandedRefs) {
325
326
  return REFERENCE_SCHEMA;
@@ -1,7 +1,9 @@
1
+ const { devDependencies } = require('./package.json');
2
+
1
3
  module.exports = {
2
4
  mongodbMemoryServerOptions: {
3
5
  binary: {
4
- version: '6.0.2',
6
+ version: devDependencies.mongodb,
5
7
  skipMD5: true,
6
8
  },
7
9
  autoStart: false,
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@bedrockio/model",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Bedrock utilities for model creation.",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "test": "jest",
8
+ "types": "tsc",
8
9
  "lint": "eslint",
9
10
  "build": "scripts/build",
10
- "types": "tsc",
11
+ "eject": "scripts/eject.js",
11
12
  "prepublishOnly": "yarn build && yarn types"
12
13
  },
13
14
  "main": "dist/cjs/index.js",
@@ -29,7 +30,7 @@
29
30
  "lodash": "^4.17.21"
30
31
  },
31
32
  "peerDependencies": {
32
- "@bedrockio/yada": "^1.0.33",
33
+ "@bedrockio/yada": "^1.0.34",
33
34
  "mongoose": "^6.9.0 || ^7.6.4"
34
35
  },
35
36
  "devDependencies": {
@@ -37,14 +38,13 @@
37
38
  "@babel/core": "^7.20.12",
38
39
  "@babel/preset-env": "^7.20.2",
39
40
  "@bedrockio/prettier-config": "^1.0.2",
40
- "@bedrockio/yada": "^1.0.33",
41
+ "@bedrockio/yada": "^1.0.34",
41
42
  "@shelf/jest-mongodb": "^4.1.7",
42
- "babel-plugin-import-replacement": "^1.0.1",
43
43
  "eslint": "^8.33.0",
44
44
  "eslint-plugin-bedrock": "^1.0.26",
45
45
  "jest": "^29.4.1",
46
46
  "jest-environment-node": "^29.4.1",
47
- "mongodb": "^5.9.1",
47
+ "mongodb": "^6.2.0",
48
48
  "mongoose": "^7.6.4",
49
49
  "prettier-eslint": "^15.0.1",
50
50
  "typescript": "^4.9.5"
package/src/schema.js CHANGED
@@ -156,10 +156,6 @@ function attributesToMongoose(attributes) {
156
156
  }
157
157
 
158
158
  function assertSchemaType(type, path) {
159
- if (type === 'Mixed') {
160
- throw new Error('Type "Mixed" is not allowed. Use "Object" instead.');
161
- }
162
-
163
159
  if (typeof type === 'string') {
164
160
  if (!isMongooseType(type)) {
165
161
  const p = path.join('.');
@@ -1,3 +1,4 @@
1
+ import mongoose from 'mongoose';
1
2
  import { isEqual } from 'lodash';
2
3
 
3
4
  import { wrapQuery } from './query';
@@ -251,7 +252,7 @@ function applyUniqueConstraints(schema) {
251
252
  }
252
253
 
253
254
  schema.pre('save', async function () {
254
- await assertUnique(this.toObject(), {
255
+ await assertUnique(this, {
255
256
  operation: this.isNew ? 'create' : 'update',
256
257
  model: this.constructor,
257
258
  schema,
@@ -367,6 +368,11 @@ function resolveUnique(schema, obj, map = {}, path = []) {
367
368
  for (let el of obj) {
368
369
  resolveUnique(schema, el, map, path);
369
370
  }
371
+ } else if (obj instanceof mongoose.Document) {
372
+ obj.schema.eachPath((key) => {
373
+ const val = obj.get(key);
374
+ resolveUnique(schema, val, map, [...path, key]);
375
+ });
370
376
  } else if (obj && typeof obj === 'object') {
371
377
  for (let [key, val] of Object.entries(obj)) {
372
378
  resolveUnique(schema, val, map, [...path, key]);
package/src/validation.js CHANGED
@@ -333,11 +333,12 @@ function getSchemaForType(type, options) {
333
333
  return yd.boolean();
334
334
  case 'Date':
335
335
  return yd.date().iso().tag(DATE_TAGS);
336
- case 'Mixed':
337
336
  case 'Object':
338
337
  return yd.object();
339
338
  case 'Array':
340
339
  return yd.array();
340
+ case 'Mixed':
341
+ return yd.any();
341
342
  case 'ObjectId':
342
343
  if (options.allowExpandedRefs) {
343
344
  return REFERENCE_SCHEMA;
@@ -24,6 +24,9 @@ export const INCLUDE_FIELD_SCHEMA: {
24
24
  validate(value: any, options?: {}): Promise<any>;
25
25
  clone(meta: any): any;
26
26
  toOpenApi(extra: any): any;
27
+ getAnyType(): {
28
+ type: string[];
29
+ };
27
30
  getDefault(): {
28
31
  default?: undefined;
29
32
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"include.d.ts","sourceRoot":"","sources":["../src/include.js"],"names":[],"mappings":"AA2BA,gDAuEC;AAMD,uDA4BC;AAGD,2DAIC;AAvHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKG"}
1
+ {"version":3,"file":"include.d.ts","sourceRoot":"","sources":["../src/include.js"],"names":[],"mappings":"AA2BA,gDAuEC;AAMD,uDA4BC;AAGD,2DAIC;AAvHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKG"}
package/types/load.d.ts CHANGED
@@ -4,73 +4,7 @@
4
4
  * @param {string} name
5
5
  * @returns mongoose.Model
6
6
  */
7
- export function loadModel(definition: object, name: string): mongoose.Model<any, any, any, any, any, mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any>, any, any, any, {
8
- [x: string]: any;
9
- }, {
10
- autoIndex?: boolean;
11
- autoCreate?: boolean;
12
- bufferCommands?: boolean;
13
- bufferTimeoutMS?: number;
14
- capped?: number | boolean | {
15
- size?: number;
16
- max?: number;
17
- autoIndexId?: boolean;
18
- };
19
- collation?: mongoose.mongo.CollationOptions;
20
- collectionOptions?: mongoose.mongo.CreateCollectionOptions;
21
- timeseries?: mongoose.mongo.TimeSeriesCollectionOptions;
22
- expireAfterSeconds?: number;
23
- expires?: string | number;
24
- collection?: string;
25
- discriminatorKey?: string;
26
- excludeIndexes?: boolean;
27
- id?: boolean;
28
- _id?: boolean;
29
- minimize?: boolean;
30
- optimisticConcurrency?: boolean;
31
- pluginTags?: string[];
32
- read?: string;
33
- writeConcern?: mongoose.mongo.WriteConcern;
34
- safe?: boolean | {
35
- w?: string | number;
36
- wtimeout?: number;
37
- j?: boolean;
38
- };
39
- shardKey?: Record<string, unknown>;
40
- strict?: boolean | "throw";
41
- strictQuery?: boolean | "throw";
42
- toJSON: {
43
- getters: boolean;
44
- versionKey: boolean;
45
- transform: (doc: any, ret: any, options: any) => void;
46
- } | mongoose.ToObjectOptions<any>;
47
- toObject: {
48
- getters: boolean;
49
- versionKey: boolean;
50
- transform: (doc: any, ret: any, options: any) => void;
51
- } | mongoose.ToObjectOptions<any>;
52
- typeKey?: string;
53
- validateBeforeSave?: boolean;
54
- validateModifiedOnly?: boolean;
55
- versionKey?: string | boolean;
56
- selectPopulatedPaths?: boolean;
57
- skipVersioning?: {
58
- [key: string]: boolean;
59
- };
60
- storeSubdocValidationError?: boolean;
61
- timestamps: boolean | mongoose.SchemaTimestampsConfig;
62
- suppressReservedKeysWarning?: boolean;
63
- statics?: {
64
- [x: string]: any;
65
- };
66
- methods?: any;
67
- query?: any;
68
- castNonArrays?: boolean;
69
- virtuals?: mongoose.SchemaOptionsVirtualsPropertyType<any, any, any>;
70
- overwriteModels?: boolean;
71
- }, any, any>> & {
72
- [x: string]: any;
73
- };
7
+ export function loadModel(definition: object, name: string): any;
74
8
  /**
75
9
  * Loads all model definitions in the given directory.
76
10
  * Returns the full loaded model set.
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,sCAJW,MAAM,QACN,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAahB;AAED;;;;GAIG;AACH,sCAFW,MAAM,mBAkBhB"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,sCAJW,MAAM,QACN,MAAM,OAahB;AAED;;;;GAIG;AACH,sCAFW,MAAM,mBAkBhB"}
package/types/schema.d.ts CHANGED
@@ -6,9 +6,7 @@
6
6
  * @param {mongoose.SchemaOptions} options
7
7
  * @returns mongoose.Schema
8
8
  */
9
- export function createSchema(definition: object, options?: mongoose.SchemaOptions): mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any>, any, any, any, {
10
- [x: string]: any;
11
- }, {
9
+ export function createSchema(definition: object, options?: mongoose.SchemaOptions): mongoose.Schema<any, mongoose.Model<any, any, any, any, any>, any, any, any, any, {
12
10
  autoIndex?: boolean;
13
11
  autoCreate?: boolean;
14
12
  bufferCommands?: boolean;
@@ -18,9 +16,8 @@ export function createSchema(definition: object, options?: mongoose.SchemaOption
18
16
  max?: number;
19
17
  autoIndexId?: boolean;
20
18
  };
21
- collation?: mongoose.mongo.CollationOptions;
22
- collectionOptions?: mongoose.mongo.CreateCollectionOptions;
23
- timeseries?: mongoose.mongo.TimeSeriesCollectionOptions;
19
+ collation?: import("mongoose/node_modules/mongodb").CollationOptions;
20
+ timeseries?: import("mongoose/node_modules/mongodb").TimeSeriesCollectionOptions;
24
21
  expireAfterSeconds?: number;
25
22
  expires?: string | number;
26
23
  collection?: string;
@@ -32,7 +29,7 @@ export function createSchema(definition: object, options?: mongoose.SchemaOption
32
29
  optimisticConcurrency?: boolean;
33
30
  pluginTags?: string[];
34
31
  read?: string;
35
- writeConcern?: mongoose.mongo.WriteConcern;
32
+ writeConcern?: import("mongoose/node_modules/mongodb").WriteConcern;
36
33
  safe?: boolean | {
37
34
  w?: string | number;
38
35
  wtimeout?: number;
@@ -45,15 +42,14 @@ export function createSchema(definition: object, options?: mongoose.SchemaOption
45
42
  getters: boolean;
46
43
  versionKey: boolean;
47
44
  transform: (doc: any, ret: any, options: any) => void;
48
- } | mongoose.ToObjectOptions<any>;
45
+ } | mongoose.ToObjectOptions;
49
46
  toObject: {
50
47
  getters: boolean;
51
48
  versionKey: boolean;
52
49
  transform: (doc: any, ret: any, options: any) => void;
53
- } | mongoose.ToObjectOptions<any>;
50
+ } | mongoose.ToObjectOptions;
54
51
  typeKey?: string;
55
52
  validateBeforeSave?: boolean;
56
- validateModifiedOnly?: boolean;
57
53
  versionKey?: string | boolean;
58
54
  selectPopulatedPaths?: boolean;
59
55
  skipVersioning?: {
@@ -61,16 +57,14 @@ export function createSchema(definition: object, options?: mongoose.SchemaOption
61
57
  };
62
58
  storeSubdocValidationError?: boolean;
63
59
  timestamps: boolean | mongoose.SchemaTimestampsConfig;
64
- suppressReservedKeysWarning?: boolean;
65
- statics?: {
66
- [x: string]: any;
67
- };
60
+ supressReservedKeysWarning?: boolean;
61
+ statics?: any;
68
62
  methods?: any;
69
63
  query?: any;
70
64
  castNonArrays?: boolean;
71
65
  virtuals?: mongoose.SchemaOptionsVirtualsPropertyType<any, any, any>;
72
66
  overwriteModels?: boolean;
73
- }, any, any>;
67
+ }, any>;
74
68
  export function normalizeAttributes(arg: any, path?: any[]): any;
75
69
  import mongoose from "mongoose";
76
70
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.js"],"names":[],"mappings":"AAoBA;;;;;;;GAOG;AACH,yCAJW,MAAM,YACN,SAAS,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAuChC;AAED,iEAsBC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.js"],"names":[],"mappings":"AAoBA;;;;;;;GAOG;AACH,yCAJW,MAAM,YACN,SAAS,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAuChC;AAED,iEAsBC"}
package/types/search.d.ts CHANGED
@@ -22,6 +22,9 @@ export function searchValidation(options?: {}): {
22
22
  validate(value: any, options?: {}): Promise<any>;
23
23
  clone(meta: any): any;
24
24
  toOpenApi(extra: any): any;
25
+ getAnyType(): {
26
+ type: string[];
27
+ };
25
28
  getDefault(): {
26
29
  default?: undefined;
27
30
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.js"],"names":[],"mappings":"AAeA,gEAmDC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBC"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.js"],"names":[],"mappings":"AAeA,gEAmDC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBC"}
@@ -1 +1 @@
1
- {"version":3,"file":"soft-delete.d.ts","sourceRoot":"","sources":["../src/soft-delete.js"],"names":[],"mappings":"AAIA,mDAIC;AAiRD,oEAsBC;AAgDD,2DAKC"}
1
+ {"version":3,"file":"soft-delete.d.ts","sourceRoot":"","sources":["../src/soft-delete.js"],"names":[],"mappings":"AAKA,mDAIC;AAiRD,oEAsBC;AAgDD,2DAKC"}
@@ -5,7 +5,7 @@
5
5
  * [Link](https://github.com/bedrockio/model#testing)
6
6
  * @returns mongoose.Model
7
7
  */
8
- export function createTestModel(...args: any[]): mongoose.Model<any, unknown, unknown, unknown, any, any>;
8
+ export function createTestModel(...args: any[]): mongoose.Model<any, unknown, unknown, unknown, any>;
9
9
  export function getTestModelName(): string;
10
10
  import mongoose from "mongoose";
11
11
  //# sourceMappingURL=testing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.js"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,0GAiBC;AAED,2CAEC"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.js"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,qGAiBC;AAED,2CAEC"}
@@ -83,6 +83,9 @@ export const OBJECT_ID_SCHEMA: {
83
83
  clone(meta: any): any;
84
84
  append(schema: any): any;
85
85
  toOpenApi(extra: any): any;
86
+ getAnyType(): {
87
+ type: string[];
88
+ };
86
89
  getDefault(): {
87
90
  default?: undefined;
88
91
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.js"],"names":[],"mappings":"AAiFA,kDAEC;AAED,oEAkFC;AAsBD,wEAkBC;AAuRD;;;EAEC;AAED;;;EAOC;AA/dD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQK"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.js"],"names":[],"mappings":"AAiFA,kDAEC;AAED,oEAkFC;AAsBD,wEAkBC;AAwRD;;;EAEC;AAED;;;EAOC;AAheD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQK"}