@ditojs/server 2.0.5 → 2.1.1

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 (53) hide show
  1. package/package.json +11 -13
  2. package/src/app/Application.js +226 -179
  3. package/src/app/Validator.js +53 -43
  4. package/src/cli/console.js +6 -4
  5. package/src/cli/db/createMigration.js +59 -30
  6. package/src/cli/db/migrate.js +6 -4
  7. package/src/cli/db/reset.js +8 -5
  8. package/src/cli/db/rollback.js +6 -4
  9. package/src/cli/db/seed.js +2 -1
  10. package/src/cli/index.js +1 -1
  11. package/src/controllers/AdminController.js +106 -85
  12. package/src/controllers/CollectionController.js +37 -30
  13. package/src/controllers/Controller.js +83 -43
  14. package/src/controllers/ControllerAction.js +27 -15
  15. package/src/controllers/ModelController.js +4 -1
  16. package/src/controllers/RelationController.js +19 -21
  17. package/src/controllers/UsersController.js +3 -4
  18. package/src/decorators/parameters.js +3 -1
  19. package/src/decorators/scope.js +1 -1
  20. package/src/errors/ControllerError.js +2 -1
  21. package/src/errors/DatabaseError.js +20 -11
  22. package/src/graph/DitoGraphProcessor.js +48 -40
  23. package/src/graph/expression.js +6 -8
  24. package/src/graph/graph.js +20 -11
  25. package/src/lib/EventEmitter.js +12 -12
  26. package/src/middleware/handleConnectMiddleware.js +16 -10
  27. package/src/middleware/handleError.js +6 -5
  28. package/src/middleware/handleSession.js +33 -29
  29. package/src/middleware/handleUser.js +2 -2
  30. package/src/middleware/index.js +1 -0
  31. package/src/middleware/logRequests.js +3 -3
  32. package/src/middleware/setupRequestStorage.js +14 -0
  33. package/src/mixins/AssetMixin.js +62 -58
  34. package/src/mixins/SessionMixin.js +13 -10
  35. package/src/mixins/TimeStampedMixin.js +33 -29
  36. package/src/mixins/UserMixin.js +130 -116
  37. package/src/models/Model.js +245 -194
  38. package/src/models/definitions/filters.js +14 -13
  39. package/src/query/QueryBuilder.js +252 -195
  40. package/src/query/QueryFilters.js +3 -3
  41. package/src/query/QueryParameters.js +2 -2
  42. package/src/query/Registry.js +8 -10
  43. package/src/schema/keywords/_validate.js +10 -8
  44. package/src/schema/properties.test.js +247 -206
  45. package/src/schema/relations.js +42 -20
  46. package/src/schema/relations.test.js +36 -19
  47. package/src/services/Service.js +8 -14
  48. package/src/storage/S3Storage.js +5 -3
  49. package/src/storage/Storage.js +16 -14
  50. package/src/utils/function.js +7 -4
  51. package/src/utils/function.test.js +30 -6
  52. package/src/utils/object.test.js +5 -1
  53. package/types/index.d.ts +244 -257
@@ -1,7 +1,16 @@
1
1
  import objection from 'objection'
2
2
  import {
3
- isString, isObject, isArray, isFunction, isPromise, asArray, merge, flatten,
4
- parseDataPath, normalizeDataPath, getValueAtDataPath,
3
+ isString,
4
+ isObject,
5
+ isArray,
6
+ isFunction,
7
+ isPromise,
8
+ asArray,
9
+ merge,
10
+ flatten,
11
+ parseDataPath,
12
+ normalizeDataPath,
13
+ getValueAtDataPath,
5
14
  mapConcurrently
6
15
  } from '@ditojs/utils'
7
16
  import { QueryBuilder } from '../query/index.js'
@@ -15,7 +24,8 @@ import { populateGraph, filterGraph } from '../graph/index.js'
15
24
  import { formatJson } from '../utils/json.js'
16
25
  import {
17
26
  ResponseError,
18
- GraphError, ModelError,
27
+ GraphError,
28
+ ModelError,
19
29
  NotFoundError,
20
30
  RelationError
21
31
  } from '../errors/index.js'
@@ -65,7 +75,8 @@ export class Model extends objection.Model {
65
75
  if (accessor in this.prototype) {
66
76
  throw new RelationError(
67
77
  `Model '${this.name}' already defines a property with name ` +
68
- `'${accessor}' that clashes with the relation accessor.`)
78
+ `'${accessor}' that clashes with the relation accessor.`
79
+ )
69
80
  }
70
81
 
71
82
  // Define an accessor on the class as well as on the prototype that when
@@ -97,16 +108,13 @@ export class Model extends objection.Model {
97
108
  }
98
109
 
99
110
  // @overridable
100
- static setup() {
101
- }
111
+ static setup() {}
102
112
 
103
113
  // @overridable
104
- static initialize() {
105
- }
114
+ static initialize() {}
106
115
 
107
116
  // @overridable
108
- $initialize() {
109
- }
117
+ $initialize() {}
110
118
 
111
119
  get $app() {
112
120
  return this.constructor.app
@@ -222,8 +230,8 @@ export class Model extends objection.Model {
222
230
  if (options.async && !options.skipValidation) {
223
231
  // Handle async validation, as supported by Dito:
224
232
  const model = new this()
225
- return model.$validate(json, options).then(
226
- json => model.$setJson(json, {
233
+ return model.$validate(json, options).then(json =>
234
+ model.$setJson(json, {
227
235
  ...options,
228
236
  skipValidation: true
229
237
  })
@@ -237,15 +245,20 @@ export class Model extends objection.Model {
237
245
  static query(trx) {
238
246
  return super.query(trx).onError(err => {
239
247
  // TODO: Shouldn't this wrapping happen on the Controller level?
240
- err = err instanceof ResponseError ? err
241
- : err instanceof objection.DBError ? this.app.createDatabaseError(err)
242
- : new ResponseError(err)
248
+ err =
249
+ err instanceof ResponseError
250
+ ? err
251
+ : err instanceof objection.DBError
252
+ ? this.app.createDatabaseError(err)
253
+ : new ResponseError(err)
243
254
  return Promise.reject(err)
244
255
  })
245
256
  }
246
257
 
247
258
  static async count(...args) {
248
- const { count } = await this.query().count(...args).first() || {}
259
+ const { count } = (await this.query()
260
+ .count(...args)
261
+ .first()) || {}
249
262
  return +count || 0
250
263
  }
251
264
 
@@ -361,25 +374,31 @@ export class Model extends objection.Model {
361
374
  }
362
375
 
363
376
  static get relationMappings() {
364
- return this._getCached('relationMappings', () => (
365
- convertRelations(this, this.definition.relations, this.app.models)
366
- ), {})
377
+ return this._getCached(
378
+ 'relationMappings',
379
+ () => convertRelations(this, this.definition.relations, this.app.models),
380
+ {}
381
+ )
367
382
  }
368
383
 
369
384
  static get jsonSchema() {
370
- return this._getCached('jsonSchema', () => {
371
- const schema = convertSchema({
372
- type: 'object',
373
- properties: this.definition.properties
374
- })
375
- addRelationSchemas(this, schema.properties)
376
- // Merge in root-level schema additions
377
- merge(schema, this.definition.schema)
378
- return {
379
- $id: this.name,
380
- ...schema
381
- }
382
- }, {})
385
+ return this._getCached(
386
+ 'jsonSchema',
387
+ () => {
388
+ const schema = convertSchema({
389
+ type: 'object',
390
+ properties: this.definition.properties
391
+ })
392
+ addRelationSchemas(this, schema.properties)
393
+ // Merge in root-level schema additions
394
+ merge(schema, this.definition.schema)
395
+ return {
396
+ $id: this.name,
397
+ ...schema
398
+ }
399
+ },
400
+ {}
401
+ )
383
402
  }
384
403
 
385
404
  static get virtualAttributes() {
@@ -389,36 +408,58 @@ export class Model extends objection.Model {
389
408
  }
390
409
 
391
410
  static get jsonAttributes() {
392
- return this._getCached('jsonSchema:jsonAttributes', () => (
393
- this.getAttributes(({ type, specificType, computed }) =>
394
- !computed && !specificType && (type === 'object' || type === 'array'))
395
- ), [])
411
+ return this._getCached(
412
+ 'jsonSchema:jsonAttributes',
413
+ () =>
414
+ this.getAttributes(
415
+ ({ type, specificType, computed }) => (
416
+ !computed &&
417
+ !specificType &&
418
+ (type === 'object' || type === 'array')
419
+ )
420
+ ),
421
+ []
422
+ )
396
423
  }
397
424
 
398
425
  static get booleanAttributes() {
399
- return this._getCached('jsonSchema:booleanAttributes', () => (
400
- this.getAttributes(({ type, computed }) =>
401
- !computed && type === 'boolean')
402
- ), [])
426
+ return this._getCached(
427
+ 'jsonSchema:booleanAttributes',
428
+ () =>
429
+ this.getAttributes(
430
+ ({ type, computed }) => !computed && type === 'boolean'
431
+ ),
432
+ []
433
+ )
403
434
  }
404
435
 
405
436
  static get dateAttributes() {
406
- return this._getCached('jsonSchema:dateAttributes', () => (
407
- this.getAttributes(({ type, computed }) =>
408
- !computed && ['date', 'datetime', 'timestamp'].includes(type))
409
- ), [])
437
+ return this._getCached(
438
+ 'jsonSchema:dateAttributes',
439
+ () =>
440
+ this.getAttributes(
441
+ ({ type, computed }) => (
442
+ !computed && ['date', 'datetime', 'timestamp'].includes(type)
443
+ )
444
+ ),
445
+ []
446
+ )
410
447
  }
411
448
 
412
449
  static get computedAttributes() {
413
- return this._getCached('jsonSchema:computedAttributes', () => (
414
- this.getAttributes(({ computed }) => computed)
415
- ), [])
450
+ return this._getCached(
451
+ 'jsonSchema:computedAttributes',
452
+ () => this.getAttributes(({ computed }) => computed),
453
+ []
454
+ )
416
455
  }
417
456
 
418
457
  static get hiddenAttributes() {
419
- return this._getCached('jsonSchema:hiddenAttributes', () => (
420
- this.getAttributes(({ hidden }) => hidden)
421
- ), [])
458
+ return this._getCached(
459
+ 'jsonSchema:hiddenAttributes',
460
+ () => this.getAttributes(({ hidden }) => hidden),
461
+ []
462
+ )
422
463
  }
423
464
 
424
465
  static getAttributes(filter) {
@@ -440,10 +481,13 @@ export class Model extends objection.Model {
440
481
  // 'jsonSchema' changes, all cached child values are invalidated.
441
482
  let entry
442
483
  for (const part of identifier.split(':')) {
443
- entry = cache[part] = cache[part] || {
444
- cache: {},
445
- value: undefined
446
- }
484
+ entry = cache[part] = (
485
+ cache[part] ||
486
+ {
487
+ cache: {},
488
+ value: undefined
489
+ }
490
+ )
447
491
  cache = entry.cache
448
492
  }
449
493
  if (entry?.value === undefined) {
@@ -707,19 +751,19 @@ export class Model extends objection.Model {
707
751
  }
708
752
  // Now check possible scope prefixes and handle them:
709
753
  switch (modifier[0]) {
710
- case '^': // Eager-applied scope:
711
- // Always apply eager-scopes, even if the model itself doesn't know it.
712
- // The scope may still be known in eager-loaded relations.
713
- // Note: `applyScope()` will handle the '^' sign.
714
- return query.applyScope(modifier)
715
- case '-': // Ignore scope:
716
- return query.ignoreScope(modifier.slice(1))
717
- case '#': // Select column:
718
- return query.select(modifier.slice(1))
719
- case '*': // Select all columns:
720
- if (modifier.length === 1) {
721
- return query.select('*')
722
- }
754
+ case '^': // Eager-applied scope:
755
+ // Always apply eager-scopes, even if the model itself doesn't know
756
+ // it. The scope may still be known in eager-loaded relations.
757
+ // Note: `applyScope()` will handle the '^' sign.
758
+ return query.applyScope(modifier)
759
+ case '-': // Ignore scope:
760
+ return query.ignoreScope(modifier.slice(1))
761
+ case '#': // Select column:
762
+ return query.select(modifier.slice(1))
763
+ case '*': // Select all columns:
764
+ if (modifier.length === 1) {
765
+ return query.select('*')
766
+ }
723
767
  }
724
768
  }
725
769
  super.modifierNotFound(query, modifier)
@@ -747,22 +791,24 @@ export class Model extends objection.Model {
747
791
  // @override
748
792
  static createValidationError({ type, message, errors, options, json }) {
749
793
  switch (type) {
750
- case 'ModelValidation':
751
- return this.app.createValidationError({
752
- type,
753
- message:
754
- message || `The provided data for the ${this.name} model is not valid`,
755
- errors,
756
- options,
757
- json
758
- })
759
- case 'RelationExpression':
760
- case 'UnallowedRelation':
761
- return new RelationError({ type, message, errors })
762
- case 'InvalidGraph':
763
- return new GraphError({ type, message, errors })
764
- default:
765
- return new ResponseError({ type, message, errors })
794
+ case 'ModelValidation':
795
+ return this.app.createValidationError({
796
+ type,
797
+ message: (
798
+ message ||
799
+ `The provided data for the ${this.name} model is not valid`
800
+ ),
801
+ errors,
802
+ options,
803
+ json
804
+ })
805
+ case 'RelationExpression':
806
+ case 'UnallowedRelation':
807
+ return new RelationError({ type, message, errors })
808
+ case 'InvalidGraph':
809
+ return new GraphError({ type, message, errors })
810
+ default:
811
+ return new ResponseError({ type, message, errors })
766
812
  }
767
813
  }
768
814
 
@@ -926,122 +972,127 @@ export class Model extends objection.Model {
926
972
  static _configureAssetsHooks(assets) {
927
973
  const assetDataPaths = Object.keys(assets)
928
974
 
929
- this.on([
930
- 'before:insert',
931
- 'before:update',
932
- 'before:delete'
933
- ], async ({ type, transaction, inputItems, asFindQuery }) => {
934
- const isInsert = type === 'before:insert'
935
- const isDelete = type === 'before:delete'
936
- // Figure out which asset data paths where actually present in the
937
- // submitted data, and only compare these. But when deleting, use all.
938
- const dataPaths = isDelete
939
- ? assetDataPaths
940
- : assetDataPaths.filter(
941
- dataPath => (
942
- // Skip check for wildcard data-paths.
943
- /^\*\*?/.test(dataPath) ||
944
- // Only keep normal data paths that match present properties.
945
- (parseDataPath(dataPath)[0] in inputItems[0])
946
- )
975
+ this.on(
976
+ [
977
+ 'before:insert',
978
+ 'before:update',
979
+ 'before:delete'
980
+ ],
981
+ async ({ type, transaction, inputItems, asFindQuery }) => {
982
+ const isInsert = type === 'before:insert'
983
+ const isDelete = type === 'before:delete'
984
+ // Figure out which asset data paths where actually present in the
985
+ // submitted data, and only compare these. But when deleting, use all.
986
+ const dataPaths = isDelete
987
+ ? assetDataPaths
988
+ : assetDataPaths.filter(
989
+ dataPath => (
990
+ // Skip check for wildcard data-paths.
991
+ /^\*\*?/.test(dataPath) ||
992
+ // Only keep normal data paths that match present properties.
993
+ (parseDataPath(dataPath)[0] in inputItems[0])
994
+ )
995
+ )
996
+ // `dataPaths` is empty in the case of an update/insert that does not
997
+ // affect the assets.
998
+ if (dataPaths.length === 0) return
999
+
1000
+ const afterItems = isDelete
1001
+ ? []
1002
+ : inputItems
1003
+ // Load the model's asset files in their current state before the query
1004
+ // is executed. For deletes, load the data for all asset data-paths.
1005
+ // Otherwise, only load the columns present in the input data.
1006
+ const beforeItems = isInsert
1007
+ ? []
1008
+ : isDelete
1009
+ ? // When deleting, it's ok to load all columns when data-paths
1010
+ // contain wildcards unfiltered, since `afterItems` will be empty
1011
+ // anyway.
1012
+ await loadAssetDataPaths(asFindQuery(), dataPaths)
1013
+ : await asFindQuery().select(
1014
+ // Select only the properties that are present in the data,
1015
+ // and which aren't the result of computed properties.
1016
+ Object.keys(inputItems[0]).filter(key => {
1017
+ const property = this.definition.properties[key]
1018
+ return property && !property.computed
1019
+ })
1020
+ )
1021
+
1022
+ const afterFilesPerDataPath = getFilesPerAssetDataPath(
1023
+ afterItems,
1024
+ dataPaths
1025
+ )
1026
+ const beforeFilesPerDataPath = getFilesPerAssetDataPath(
1027
+ beforeItems,
1028
+ dataPaths
947
1029
  )
948
- // `dataPaths` is empty in the case of an update/insert that does not
949
- // affect the assets.
950
- if (dataPaths.length === 0) return
951
-
952
- const afterItems = isDelete
953
- ? []
954
- : inputItems
955
- // Load the model's asset files in their current state before the query is
956
- // executed. For deletes, load the data for all asset data-paths.
957
- // Otherwise, only load the columns present in the input data.
958
- const beforeItems = isInsert
959
- ? []
960
- : isDelete
961
- // When deleting it's ok to load all columns when data-paths contain
962
- // wildcards unfiltered, since `afterItems` will be empty anyway.
963
- ? await loadAssetDataPaths(asFindQuery(), dataPaths)
964
- : await asFindQuery().select(
965
- // Select only the properties that are present in the data,
966
- // and which aren't the result of computed properties.
967
- Object.keys(inputItems[0]).filter(key => {
968
- const property = this.definition.properties[key]
969
- return property && !property.computed
970
- })
971
- )
972
-
973
- const afterFilesPerDataPath = getFilesPerAssetDataPath(
974
- afterItems,
975
- dataPaths
976
- )
977
- const beforeFilesPerDataPath = getFilesPerAssetDataPath(
978
- beforeItems,
979
- dataPaths
980
- )
981
1030
 
982
- const importedFiles = []
983
- const modifiedFiles = []
984
-
985
- if (transaction.rollback) {
986
- // Prevent wrong memory leak error messages when installing more than 10
987
- // 'rollback' handlers, which can happen with more complex queries.
988
- transaction.setMaxListeners(0)
989
- transaction.on('rollback', async error => {
990
- if (importedFiles.length > 0) {
991
- console.info(
992
- `Received '${error}', removing imported files again: ${
993
- importedFiles.map(file => `'${file.name}'`)
994
- }`
995
- )
996
- await mapConcurrently(
997
- importedFiles,
998
- file => file.storage.removeFile(file)
999
- )
1000
- }
1001
- if (modifiedFiles.length > 0) {
1002
- // TODO: `modifiedFiles` should be restored as well, but that's far
1003
- // from trivial since no backup is kept in `handleModifiedAssets`
1004
- console.warn(
1005
- `Unable to restore these already modified files: ${
1006
- modifiedFiles.map(file => `'${file.name}'`)
1007
- }`
1008
- )
1009
- }
1010
- })
1011
- }
1031
+ const importedFiles = []
1032
+ const modifiedFiles = []
1033
+
1034
+ if (transaction.rollback) {
1035
+ // Prevent wrong memory leak error messages when installing more than
1036
+ // 10 'rollback' handlers, which can happen with more complex queries.
1037
+ transaction.setMaxListeners(0)
1038
+ transaction.on('rollback', async error => {
1039
+ if (importedFiles.length > 0) {
1040
+ console.info(
1041
+ `Received '${error}', removing imported files again: ${
1042
+ importedFiles.map(file => `'${file.name}'`)
1043
+ }`
1044
+ )
1045
+ await mapConcurrently(
1046
+ importedFiles,
1047
+ file => file.storage.removeFile(file)
1048
+ )
1049
+ }
1050
+ if (modifiedFiles.length > 0) {
1051
+ // TODO: `modifiedFiles` should be restored as well, but that's
1052
+ // far from trivial since no backup is kept in
1053
+ // `handleModifiedAssets()`
1054
+ console.warn(
1055
+ `Unable to restore these already modified files: ${
1056
+ modifiedFiles.map(file => `'${file.name}'`)
1057
+ }`
1058
+ )
1059
+ }
1060
+ })
1061
+ }
1012
1062
 
1013
- for (const dataPath of dataPaths) {
1014
- const storage = this.app.getStorage(assets[dataPath].storage)
1015
- const beforeFiles = beforeFilesPerDataPath[dataPath] || []
1016
- const afterFiles = afterFilesPerDataPath[dataPath] || []
1017
- const beforeByKey = mapFilesByKey(beforeFiles)
1018
- const afterByKey = mapFilesByKey(afterFiles)
1019
- const removedFiles = beforeFiles.filter(file => !afterByKey[file.key])
1020
- const addedFiles = afterFiles.filter(file => !beforeByKey[file.key])
1021
- // Also handle modified files, which are files where the data property
1022
- // is changed before update / patch, meaning the file is changed.
1023
- // NOTE: This will change the content for all the references to it,
1024
- // and thus should only really be used when there's only one reference.
1025
- const modifiedFiles = afterFiles.filter(
1026
- file => file.data && beforeByKey[file.key]
1027
- )
1028
- importedFiles.push(
1029
- ...await this.app.handleAddedAndRemovedAssets(
1030
- storage,
1031
- addedFiles,
1032
- removedFiles,
1033
- transaction
1063
+ for (const dataPath of dataPaths) {
1064
+ const storage = this.app.getStorage(assets[dataPath].storage)
1065
+ const beforeFiles = beforeFilesPerDataPath[dataPath] || []
1066
+ const afterFiles = afterFilesPerDataPath[dataPath] || []
1067
+ const beforeByKey = mapFilesByKey(beforeFiles)
1068
+ const afterByKey = mapFilesByKey(afterFiles)
1069
+ const removedFiles = beforeFiles.filter(file => !afterByKey[file.key])
1070
+ const addedFiles = afterFiles.filter(file => !beforeByKey[file.key])
1071
+ // Also handle modified files, which are files where the data property
1072
+ // is changed before update / patch, meaning the file is changed.
1073
+ // NOTE: This will change the content for all the references to it,
1074
+ // and so should only really be used when there's only one reference.
1075
+ const modifiedFiles = afterFiles.filter(
1076
+ file => file.data && beforeByKey[file.key]
1034
1077
  )
1035
- )
1036
- modifiedFiles.push(
1037
- ...await this.app.handleModifiedAssets(
1038
- storage,
1039
- modifiedFiles,
1040
- transaction
1078
+ importedFiles.push(
1079
+ ...(await this.app.handleAddedAndRemovedAssets(
1080
+ storage,
1081
+ addedFiles,
1082
+ removedFiles,
1083
+ transaction
1084
+ ))
1041
1085
  )
1042
- )
1086
+ modifiedFiles.push(
1087
+ ...(await this.app.handleModifiedAssets(
1088
+ storage,
1089
+ modifiedFiles,
1090
+ transaction
1091
+ ))
1092
+ )
1093
+ }
1043
1094
  }
1044
- })
1095
+ )
1045
1096
  }
1046
1097
  }
1047
1098
 
@@ -1055,7 +1106,7 @@ const metaMap = new WeakMap()
1055
1106
  function getMeta(modelClass, key, value) {
1056
1107
  let meta = metaMap.get(modelClass)
1057
1108
  if (!meta) {
1058
- metaMap.set(modelClass, meta = {})
1109
+ metaMap.set(modelClass, (meta = {}))
1059
1110
  }
1060
1111
  if (!(key in meta)) {
1061
1112
  meta[key] = isFunction(value) ? value() : value
@@ -47,15 +47,15 @@ function convertFilterObject(name, object) {
47
47
  : queryFilter
48
48
  const func = properties
49
49
  ? (query, ...args) => {
50
- // When the filter provides multiple properties, match them
51
- // all, but combine the expressions with OR.
52
- for (const property of properties) {
53
- query.orWhere(query => queryHandler(query, property, ...args))
50
+ // When the filter provides multiple properties, match them
51
+ // all, but combine the expressions with OR.
52
+ for (const property of properties) {
53
+ query.orWhere(query => queryHandler(query, property, ...args))
54
+ }
54
55
  }
55
- }
56
56
  : (query, ...args) => {
57
- queryHandler(query, name, ...args)
58
- }
57
+ queryHandler(query, name, ...args)
58
+ }
59
59
  return addHandlerSettings(func, queryFilter)
60
60
  }
61
61
  }
@@ -75,12 +75,12 @@ function wrapWithValidation(filter, name, app) {
75
75
  })
76
76
  if (validator?.validate) {
77
77
  return (query, ...args) => {
78
- // Convert args to object for validation:
78
+ // Convert args to object for validation:
79
79
  const object = {}
80
80
  let index = 0
81
81
  for (const { name } of validator.list) {
82
- // Use dataName if no name is given, see:
83
- // Application.compileParametersValidator()
82
+ // Use dataName if no name is given, see:
83
+ // Application.compileParametersValidator()
84
84
  object[name || dataName] = args[index++]
85
85
  }
86
86
  try {
@@ -88,11 +88,12 @@ function wrapWithValidation(filter, name, app) {
88
88
  } catch (error) {
89
89
  throw app.createValidationError({
90
90
  type: 'FilterValidation',
91
- message:
92
- `The provided data for query filter '${name}' is not valid`,
91
+ message: `The provided data for query filter '${
92
+ name
93
+ }' is not valid`,
93
94
  errors: app.validator.prefixInstancePaths(
94
95
  error.errors,
95
- `.${name}`
96
+ `.${name}`
96
97
  )
97
98
  })
98
99
  }