@bedrockio/model 0.1.9 → 0.1.11

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.
@@ -107,13 +107,15 @@ function validateDefinition(definition) {
107
107
  }
108
108
  }
109
109
  function resolveSort(sort, schema) {
110
- if (!Array.isArray(sort)) {
110
+ if (!sort) {
111
+ sort = [];
112
+ } else if (!Array.isArray(sort)) {
111
113
  sort = [sort];
112
114
  }
113
115
  for (let {
114
116
  field
115
117
  } of sort) {
116
- if (!schema.path(field)) {
118
+ if (!field || !schema.path(field)) {
117
119
  throw new Error(`Unknown sort field "${field}".`);
118
120
  }
119
121
  }
@@ -19,31 +19,33 @@ var _softDelete = require("./soft-delete");
19
19
  var _utils = require("./utils");
20
20
  var _include = require("./include");
21
21
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
- const DATE_SCHEMA = _yada.default.date().iso().tag({
22
+ const DATE_TAGS = {
23
23
  'x-schema': 'DateTime',
24
24
  'x-description': 'A `string` in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.'
25
+ };
26
+ const OBJECT_ID_SCHEMA = _yada.default.string().mongo().tag({
27
+ 'x-schema': 'ObjectId',
28
+ 'x-description': 'A 24 character hexadecimal string representing a Mongo [ObjectId](https://bit.ly/3YPtGlU).'
25
29
  });
26
- const OBJECT_ID_DESCRIPTION = `
30
+ exports.OBJECT_ID_SCHEMA = OBJECT_ID_SCHEMA;
31
+ const REFERENCE_SCHEMA = _yada.default.allow(OBJECT_ID_SCHEMA, _yada.default.object({
32
+ id: OBJECT_ID_SCHEMA.required()
33
+ }).custom(obj => {
34
+ return obj.id;
35
+ })).tag({
36
+ 'x-schema': 'Reference',
37
+ 'x-description': `
27
38
  A 24 character hexadecimal string representing a Mongo [ObjectId](https://bit.ly/3YPtGlU).
28
39
  An object with an \`id\` field may also be passed, which will be converted into a string.
29
- `;
30
- const OBJECT_ID_SCHEMA = _yada.default.custom(async val => {
31
- const id = String(val.id || val);
32
- await namedSchemas.objectId.validate(id);
33
- return id;
34
- }).tag({
35
- type: 'ObjectId',
36
- 'x-schema': 'ObjectId',
37
- 'x-description': OBJECT_ID_DESCRIPTION.trim()
40
+ `.trim()
38
41
  });
39
- exports.OBJECT_ID_SCHEMA = OBJECT_ID_SCHEMA;
40
42
  const namedSchemas = {
41
43
  // Email is special as we are assuming that in
42
44
  // all cases lowercase should be allowed but coerced.
43
45
  email: _yada.default.string().lowercase().email(),
44
46
  // Force "objectId" to have parity with refs.
45
47
  // "mongo" is notably excluded here for this reason.
46
- objectId: _yada.default.string().mongo(),
48
+ objectId: OBJECT_ID_SCHEMA,
47
49
  ascii: _yada.default.string().ascii(),
48
50
  base64: _yada.default.string().base64(),
49
51
  btc: _yada.default.string().btc(),
@@ -77,6 +79,7 @@ function applyValidation(schema, definition) {
77
79
  allowIncludes: true,
78
80
  stripDeleted: true,
79
81
  stripTimestamps: true,
82
+ allowExpandedRefs: true,
80
83
  requireWriteAccess: true,
81
84
  ...(hasUnique && {
82
85
  assertUniqueOptions: {
@@ -94,6 +97,7 @@ function applyValidation(schema, definition) {
94
97
  stripUnknown: true,
95
98
  stripDeleted: true,
96
99
  stripTimestamps: true,
100
+ allowExpandedRefs: true,
97
101
  requireWriteAccess: true,
98
102
  ...(hasUnique && {
99
103
  assertUniqueOptions: {
@@ -213,7 +217,7 @@ function getObjectSchema(arg, options) {
213
217
  }
214
218
  return schema;
215
219
  } else {
216
- return getSchemaForType(arg);
220
+ return getSchemaForType(arg, options);
217
221
  }
218
222
  }
219
223
  function getArraySchema(arr, options) {
@@ -247,11 +251,14 @@ function getSchemaForTypedef(typedef, options = {}) {
247
251
  } else if (typeof type === 'object') {
248
252
  schema = getObjectSchema(type, options);
249
253
  } else {
250
- schema = getSchemaForType(type);
254
+ schema = getSchemaForType(type, options);
251
255
  }
252
256
  if (isRequired(typedef, options)) {
253
257
  schema = schema.required();
254
258
  }
259
+ if (typedef.default) {
260
+ schema = schema.default(typedef.default);
261
+ }
255
262
  if (typedef.validate?.schema) {
256
263
  schema = schema.append(typedef.validate.schema);
257
264
  } else if (typeof typedef.validate === 'function') {
@@ -280,7 +287,7 @@ function getSchemaForTypedef(typedef, options = {}) {
280
287
  }
281
288
  return schema;
282
289
  }
283
- function getSchemaForType(type) {
290
+ function getSchemaForType(type, options) {
284
291
  switch (type) {
285
292
  case 'String':
286
293
  return _yada.default.string();
@@ -289,14 +296,18 @@ function getSchemaForType(type) {
289
296
  case 'Boolean':
290
297
  return _yada.default.boolean();
291
298
  case 'Date':
292
- return DATE_SCHEMA;
299
+ return _yada.default.date().iso().tag(DATE_TAGS);
293
300
  case 'Mixed':
294
301
  case 'Object':
295
302
  return _yada.default.object();
296
303
  case 'Array':
297
304
  return _yada.default.array();
298
305
  case 'ObjectId':
299
- return OBJECT_ID_SCHEMA;
306
+ if (options.allowExpandedRefs) {
307
+ return REFERENCE_SCHEMA;
308
+ } else {
309
+ return OBJECT_ID_SCHEMA;
310
+ }
300
311
  default:
301
312
  throw new TypeError(`Unknown schema type ${type}`);
302
313
  }
@@ -315,19 +326,19 @@ function getSearchSchema(schema, type) {
315
326
  } else if (type === 'Date') {
316
327
  return _yada.default.allow(schema, _yada.default.array(schema), _yada.default.object({
317
328
  lt: _yada.default.date().iso().tag({
318
- 'x-ref': 'DateTime',
329
+ ...DATE_TAGS,
319
330
  description: 'Select dates occurring before.'
320
331
  }),
321
332
  gt: _yada.default.date().iso().tag({
322
- 'x-ref': 'DateTime',
333
+ ...DATE_TAGS,
323
334
  description: 'Select dates occurring after.'
324
335
  }),
325
336
  lte: _yada.default.date().iso().tag({
326
- 'x-ref': 'DateTime',
337
+ ...DATE_TAGS,
327
338
  description: 'Select dates occurring on or before.'
328
339
  }),
329
340
  gte: _yada.default.date().iso().tag({
330
- 'x-ref': 'DateTime',
341
+ ...DATE_TAGS,
331
342
  description: 'Select dates occurring on or after.'
332
343
  })
333
344
  }).tag({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrockio/model",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Bedrock utilities for model creation.",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/search.js CHANGED
@@ -119,11 +119,13 @@ function validateDefinition(definition) {
119
119
  }
120
120
 
121
121
  function resolveSort(sort, schema) {
122
- if (!Array.isArray(sort)) {
122
+ if (!sort) {
123
+ sort = [];
124
+ } else if (!Array.isArray(sort)) {
123
125
  sort = [sort];
124
126
  }
125
127
  for (let { field } of sort) {
126
- if (!schema.path(field)) {
128
+ if (!field || !schema.path(field)) {
127
129
  throw new Error(`Unknown sort field "${field}".`);
128
130
  }
129
131
  }
package/src/validation.js CHANGED
@@ -10,27 +10,35 @@ import { hasUniqueConstraints, assertUnique } from './soft-delete';
10
10
  import { isMongooseSchema, isSchemaTypedef } from './utils';
11
11
  import { INCLUDE_FIELD_SCHEMA } from './include';
12
12
 
13
- const DATE_SCHEMA = yd.date().iso().tag({
13
+ const DATE_TAGS = {
14
14
  'x-schema': 'DateTime',
15
15
  'x-description':
16
16
  'A `string` in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.',
17
+ };
18
+
19
+ export const OBJECT_ID_SCHEMA = yd.string().mongo().tag({
20
+ 'x-schema': 'ObjectId',
21
+ 'x-description':
22
+ 'A 24 character hexadecimal string representing a Mongo [ObjectId](https://bit.ly/3YPtGlU).',
17
23
  });
18
24
 
19
- const OBJECT_ID_DESCRIPTION = `
25
+ const REFERENCE_SCHEMA = yd
26
+ .allow(
27
+ OBJECT_ID_SCHEMA,
28
+ yd
29
+ .object({
30
+ id: OBJECT_ID_SCHEMA.required(),
31
+ })
32
+ .custom((obj) => {
33
+ return obj.id;
34
+ })
35
+ )
36
+ .tag({
37
+ 'x-schema': 'Reference',
38
+ 'x-description': `
20
39
  A 24 character hexadecimal string representing a Mongo [ObjectId](https://bit.ly/3YPtGlU).
21
40
  An object with an \`id\` field may also be passed, which will be converted into a string.
22
- `;
23
-
24
- export const OBJECT_ID_SCHEMA = yd
25
- .custom(async (val) => {
26
- const id = String(val.id || val);
27
- await namedSchemas.objectId.validate(id);
28
- return id;
29
- })
30
- .tag({
31
- type: 'ObjectId',
32
- 'x-schema': 'ObjectId',
33
- 'x-description': OBJECT_ID_DESCRIPTION.trim(),
41
+ `.trim(),
34
42
  });
35
43
 
36
44
  const namedSchemas = {
@@ -39,7 +47,7 @@ const namedSchemas = {
39
47
  email: yd.string().lowercase().email(),
40
48
  // Force "objectId" to have parity with refs.
41
49
  // "mongo" is notably excluded here for this reason.
42
- objectId: yd.string().mongo(),
50
+ objectId: OBJECT_ID_SCHEMA,
43
51
 
44
52
  ascii: yd.string().ascii(),
45
53
  base64: yd.string().base64(),
@@ -79,6 +87,7 @@ export function applyValidation(schema, definition) {
79
87
  allowIncludes: true,
80
88
  stripDeleted: true,
81
89
  stripTimestamps: true,
90
+ allowExpandedRefs: true,
82
91
  requireWriteAccess: true,
83
92
  ...(hasUnique && {
84
93
  assertUniqueOptions: {
@@ -100,6 +109,7 @@ export function applyValidation(schema, definition) {
100
109
  stripUnknown: true,
101
110
  stripDeleted: true,
102
111
  stripTimestamps: true,
112
+ allowExpandedRefs: true,
103
113
  requireWriteAccess: true,
104
114
  ...(hasUnique && {
105
115
  assertUniqueOptions: {
@@ -216,7 +226,7 @@ function getObjectSchema(arg, options) {
216
226
 
217
227
  return schema;
218
228
  } else {
219
- return getSchemaForType(arg);
229
+ return getSchemaForType(arg, options);
220
230
  }
221
231
  }
222
232
 
@@ -252,12 +262,15 @@ function getSchemaForTypedef(typedef, options = {}) {
252
262
  } else if (typeof type === 'object') {
253
263
  schema = getObjectSchema(type, options);
254
264
  } else {
255
- schema = getSchemaForType(type);
265
+ schema = getSchemaForType(type, options);
256
266
  }
257
267
 
258
268
  if (isRequired(typedef, options)) {
259
269
  schema = schema.required();
260
270
  }
271
+ if (typedef.default) {
272
+ schema = schema.default(typedef.default);
273
+ }
261
274
  if (typedef.validate?.schema) {
262
275
  schema = schema.append(typedef.validate.schema);
263
276
  } else if (typeof typedef.validate === 'function') {
@@ -288,7 +301,7 @@ function getSchemaForTypedef(typedef, options = {}) {
288
301
  return schema;
289
302
  }
290
303
 
291
- function getSchemaForType(type) {
304
+ function getSchemaForType(type, options) {
292
305
  switch (type) {
293
306
  case 'String':
294
307
  return yd.string();
@@ -297,14 +310,18 @@ function getSchemaForType(type) {
297
310
  case 'Boolean':
298
311
  return yd.boolean();
299
312
  case 'Date':
300
- return DATE_SCHEMA;
313
+ return yd.date().iso().tag(DATE_TAGS);
301
314
  case 'Mixed':
302
315
  case 'Object':
303
316
  return yd.object();
304
317
  case 'Array':
305
318
  return yd.array();
306
319
  case 'ObjectId':
307
- return OBJECT_ID_SCHEMA;
320
+ if (options.allowExpandedRefs) {
321
+ return REFERENCE_SCHEMA;
322
+ } else {
323
+ return OBJECT_ID_SCHEMA;
324
+ }
308
325
  default:
309
326
  throw new TypeError(`Unknown schema type ${type}`);
310
327
  }
@@ -341,22 +358,34 @@ function getSearchSchema(schema, type) {
341
358
  yd.array(schema),
342
359
  yd
343
360
  .object({
344
- lt: yd.date().iso().tag({
345
- 'x-ref': 'DateTime',
346
- description: 'Select dates occurring before.',
347
- }),
348
- gt: yd.date().iso().tag({
349
- 'x-ref': 'DateTime',
350
- description: 'Select dates occurring after.',
351
- }),
352
- lte: yd.date().iso().tag({
353
- 'x-ref': 'DateTime',
354
- description: 'Select dates occurring on or before.',
355
- }),
356
- gte: yd.date().iso().tag({
357
- 'x-ref': 'DateTime',
358
- description: 'Select dates occurring on or after.',
359
- }),
361
+ lt: yd
362
+ .date()
363
+ .iso()
364
+ .tag({
365
+ ...DATE_TAGS,
366
+ description: 'Select dates occurring before.',
367
+ }),
368
+ gt: yd
369
+ .date()
370
+ .iso()
371
+ .tag({
372
+ ...DATE_TAGS,
373
+ description: 'Select dates occurring after.',
374
+ }),
375
+ lte: yd
376
+ .date()
377
+ .iso()
378
+ .tag({
379
+ ...DATE_TAGS,
380
+ description: 'Select dates occurring on or before.',
381
+ }),
382
+ gte: yd
383
+ .date()
384
+ .iso()
385
+ .tag({
386
+ ...DATE_TAGS,
387
+ description: 'Select dates occurring on or after.',
388
+ }),
360
389
  })
361
390
  .tag({
362
391
  'x-schema': 'DateRange',
@@ -9,5 +9,95 @@ export function getTupleValidator(types: any): {
9
9
  (val: any): Promise<void>;
10
10
  schema: any;
11
11
  };
12
- export const OBJECT_ID_SCHEMA: import("@bedrockio/yada/types/Schema").default;
12
+ export const OBJECT_ID_SCHEMA: {
13
+ length(length: number): any;
14
+ min(length: number): any;
15
+ max(length: number): any;
16
+ trim(): any;
17
+ lowercase(assert?: boolean): any;
18
+ uppercase(assert?: boolean): any;
19
+ match(reg: RegExp): any;
20
+ email(): any;
21
+ phone(): any;
22
+ hex(): any;
23
+ md5(): any;
24
+ sha1(): any;
25
+ ascii(): any;
26
+ base64(options?: {
27
+ urlSafe?: boolean;
28
+ }): any;
29
+ creditCard(): any;
30
+ ip(): any;
31
+ country(): any;
32
+ locale(): any;
33
+ jwt(): any;
34
+ slug(): any;
35
+ latlng(): any;
36
+ postalCode(locale?: string): any;
37
+ password(options?: {
38
+ minLength?: number;
39
+ minNumbers?: number;
40
+ minSymbols?: number;
41
+ minLowercase?: number;
42
+ minUppercase?: number;
43
+ }): any;
44
+ url(options?: {
45
+ require_protocol?: boolean;
46
+ require_valid_protocol?: boolean;
47
+ require_host?: boolean;
48
+ require_port?: boolean;
49
+ allow_protocol_relative_urls?: boolean;
50
+ allow_fragments?: boolean;
51
+ allow_query_components?: boolean;
52
+ validate_length?: boolean;
53
+ protocols?: string[];
54
+ }): any;
55
+ domain(options?: {
56
+ require_tld?: boolean;
57
+ allow_underscores?: boolean;
58
+ allow_trailing_dot?: boolean;
59
+ allow_numeric_tld?: boolean;
60
+ allow_wildcard?: boolean;
61
+ ignore_max_length?: boolean;
62
+ }): any;
63
+ uuid(version?: 1 | 2 | 5 | 3 | 4): any;
64
+ btc(): any;
65
+ eth(): any;
66
+ swift(): any;
67
+ mongo(): any;
68
+ format(name: any, fn: any): import("@bedrockio/yada/types/TypeSchema").default;
69
+ toString(): any;
70
+ assertions: any[];
71
+ meta: {};
72
+ required(): any;
73
+ default(value: any): any;
74
+ custom(...args: import("@bedrockio/yada/types/Schema").CustomSignature): any;
75
+ strip(strip: any): any;
76
+ allow(...set: any[]): any;
77
+ reject(...set: any[]): any;
78
+ message(message: any): any;
79
+ tag(tags: any): any;
80
+ description(description: any): any;
81
+ options(options: any): any;
82
+ validate(value: any, options?: {}): Promise<any>;
83
+ clone(meta: any): any;
84
+ append(schema: any): any;
85
+ toOpenApi(extra: any): any;
86
+ expandExtra(extra?: {}): {};
87
+ assertEnum(set: any, allow: any): any;
88
+ assert(type: any, fn: any): any;
89
+ pushAssertion(assertion: any): void;
90
+ transform(fn: any): any;
91
+ getSortIndex(type: any): number;
92
+ runAssertion(assertion: any, value: any, options?: {}): Promise<any>;
93
+ enumToOpenApi(): {
94
+ type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
95
+ enum: any;
96
+ oneOf?: undefined;
97
+ } | {
98
+ oneOf: any[];
99
+ type?: undefined;
100
+ enum?: undefined;
101
+ };
102
+ };
13
103
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.js"],"names":[],"mappings":"AAiEA,kDAEC;AAED,oEA4EC;AAsBD,wEAkBC;AA0PD;;;EAEC;AAED;;;EAOC;AAvaD,8EAUK"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.js"],"names":[],"mappings":"AAyEA,kDAEC;AAED,oEA8EC;AAsBD,wEAkBC;AA6QD;;;EAEC;AAED;;;EAOC;AAzcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAIG"}