@contember/schema-utils 1.1.0-alpha.3 → 1.1.0-alpha.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 (75) hide show
  1. package/dist/src/acl/AllowAllPermissionFactory.d.ts.map +1 -1
  2. package/dist/src/acl/AllowAllPermissionFactory.js.map +1 -1
  3. package/dist/src/acl/index.js +5 -1
  4. package/dist/src/acl/index.js.map +1 -1
  5. package/dist/src/dataUtils.d.ts +2 -2
  6. package/dist/src/dataUtils.d.ts.map +1 -1
  7. package/dist/src/dataUtils.js +1 -1
  8. package/dist/src/dataUtils.js.map +1 -1
  9. package/dist/src/index.d.ts +2 -0
  10. package/dist/src/index.d.ts.map +1 -1
  11. package/dist/src/index.js +25 -2
  12. package/dist/src/index.js.map +1 -1
  13. package/dist/src/model/NamingHelper.d.ts +1 -1
  14. package/dist/src/model/NamingHelper.d.ts.map +1 -1
  15. package/dist/src/model/NamingHelper.js.map +1 -1
  16. package/dist/src/model/index.js +5 -1
  17. package/dist/src/model/index.js.map +1 -1
  18. package/dist/src/tsconfig.tsbuildinfo +1 -1
  19. package/dist/src/type-schema/acl.d.ts +8 -0
  20. package/dist/src/type-schema/acl.d.ts.map +1 -0
  21. package/dist/src/type-schema/acl.js +88 -0
  22. package/dist/src/type-schema/acl.js.map +1 -0
  23. package/dist/src/type-schema/index.d.ts +4 -0
  24. package/dist/src/type-schema/index.d.ts.map +1 -0
  25. package/dist/src/type-schema/index.js +20 -0
  26. package/dist/src/type-schema/index.js.map +1 -0
  27. package/dist/src/type-schema/model.d.ts +30 -0
  28. package/dist/src/type-schema/model.d.ts.map +1 -0
  29. package/dist/src/type-schema/model.js +148 -0
  30. package/dist/src/type-schema/model.js.map +1 -0
  31. package/dist/src/type-schema/validation.d.ts +15 -0
  32. package/dist/src/type-schema/validation.d.ts.map +1 -0
  33. package/dist/src/type-schema/validation.js +95 -0
  34. package/dist/src/type-schema/validation.js.map +1 -0
  35. package/dist/src/utils/index.js +5 -1
  36. package/dist/src/utils/index.js.map +1 -1
  37. package/dist/src/validation/AclValidator.d.ts +1 -2
  38. package/dist/src/validation/AclValidator.d.ts.map +1 -1
  39. package/dist/src/validation/AclValidator.js +22 -197
  40. package/dist/src/validation/AclValidator.js.map +1 -1
  41. package/dist/src/validation/ModelValidator.d.ts +1 -1
  42. package/dist/src/validation/ModelValidator.d.ts.map +1 -1
  43. package/dist/src/validation/ModelValidator.js +48 -219
  44. package/dist/src/validation/ModelValidator.js.map +1 -1
  45. package/dist/src/validation/SchemaValidator.d.ts.map +1 -1
  46. package/dist/src/validation/SchemaValidator.js +5 -18
  47. package/dist/src/validation/SchemaValidator.js.map +1 -1
  48. package/dist/src/validation/ValidationValidator.d.ts +1 -3
  49. package/dist/src/validation/ValidationValidator.d.ts.map +1 -1
  50. package/dist/src/validation/ValidationValidator.js +28 -201
  51. package/dist/src/validation/ValidationValidator.js.map +1 -1
  52. package/dist/src/validation/index.d.ts +2 -0
  53. package/dist/src/validation/index.d.ts.map +1 -1
  54. package/dist/src/validation/index.js +7 -1
  55. package/dist/src/validation/index.js.map +1 -1
  56. package/package.json +3 -2
  57. package/src/acl/AllowAllPermissionFactory.ts +2 -2
  58. package/src/dataUtils.ts +3 -3
  59. package/src/index.ts +8 -0
  60. package/src/model/NamingHelper.ts +1 -1
  61. package/src/tsconfig.json +3 -0
  62. package/src/type-schema/acl.ts +100 -0
  63. package/src/type-schema/index.ts +3 -0
  64. package/src/type-schema/model.ts +173 -0
  65. package/src/type-schema/validation.ts +100 -0
  66. package/src/validation/AclValidator.ts +42 -239
  67. package/src/validation/ModelValidator.ts +63 -263
  68. package/src/validation/SchemaValidator.ts +6 -19
  69. package/src/validation/ValidationValidator.ts +41 -222
  70. package/src/validation/index.ts +2 -0
  71. package/dist/src/validation/utils.d.ts +0 -18
  72. package/dist/src/validation/utils.d.ts.map +0 -1
  73. package/dist/src/validation/utils.js +0 -36
  74. package/dist/src/validation/utils.js.map +0 -1
  75. package/src/validation/utils.ts +0 -45
@@ -1,245 +1,88 @@
1
1
  import { Model } from '@contember/schema'
2
2
  import { ErrorBuilder, ValidationError } from './errors'
3
- import { everyIs, isObject, UnknownObject } from './utils'
4
3
  import { acceptEveryFieldVisitor, getTargetEntity, isInverseRelation, isOwningRelation } from '../model'
5
4
 
6
5
  const IDENTIFIER_PATTERN = /^[_a-zA-Z][_a-zA-Z0-9]*$/
7
6
  const RESERVED_WORDS = ['and', 'or', 'not']
8
7
 
8
+
9
9
  export class ModelValidator {
10
10
  constructor(private readonly model: Model.Schema) {}
11
11
 
12
- public validate(): [Model.Schema, ValidationError[]] {
13
- const model = this.model as unknown
12
+ public validate(): ValidationError[] {
14
13
  const errorBuilder = new ErrorBuilder([], [])
15
- let validModel: Model.Schema
16
- if (!isObject(model)) {
17
- errorBuilder.add('Must be an object')
18
- validModel = { entities: {}, enums: {} }
19
- } else {
20
- const enums = this.validateEnums(model.enums, errorBuilder.for('enums'))
21
- const entities = this.validateEntities(model.entities, errorBuilder.for('entities'))
22
- validModel = { enums, entities }
23
- }
24
- this.validateCollisions(Object.values(validModel.entities), errorBuilder.for('entities'))
25
- return [validModel, errorBuilder.errors]
14
+ this.validateEnums(this.model.enums, errorBuilder.for('enums'))
15
+ this.validateEntities(this.model.entities, errorBuilder.for('entities'))
16
+ this.validateCollisions(Object.values(this.model.entities), errorBuilder.for('entities'))
17
+ return errorBuilder.errors
26
18
  }
27
19
 
28
- private validateEnums(enums: unknown, errors: ErrorBuilder): Model.Schema['enums'] {
29
- if (!enums) {
30
- errors.add('Enums definitions are missing')
31
- return {}
32
- }
33
- if (!isObject(enums)) {
34
- errors.add('Enums must be an object')
35
- return {}
36
- }
37
- const validEnums: Model.Schema['enums'] = {}
38
- enums: for (const [enumName, enumValues] of Object.entries(enums)) {
39
- if (!Array.isArray(enumValues) || !everyIs(enumValues, (it): it is string => typeof it === 'string')) {
40
- errors.for(enumName).add('Enum values must be an array of strings')
41
- continue
42
- }
43
- if (enumValues.length === 0) {
44
- errors.for(enumName).add('Enum must have at least one value')
45
- }
20
+ private validateEnums(enums: Model.Schema['enums'], errors: ErrorBuilder): void {
21
+ for (const [enumName, enumValues] of Object.entries(enums)) {
46
22
  for (const value of enumValues) {
47
- const valueErrors = errors.for(value)
48
- if (!this.validateIdentifier(value, valueErrors)) {
49
- continue enums
50
- }
23
+ const valueErrors = errors.for(enumName, value)
24
+ this.validateIdentifier(value, valueErrors)
51
25
  }
52
- validEnums[enumName] = enumValues
53
26
  }
54
- return validEnums
55
27
  }
56
28
 
57
- private validateEntities(entities: unknown, errors: ErrorBuilder): Model.Schema['entities'] {
58
- if (!entities) {
59
- errors.add('Entities definitions are missing')
60
- return {}
61
- }
62
- if (!isObject(entities)) {
63
- errors.add('Entities must be an object')
64
- return {}
65
- }
66
- const validEntities: Model.Schema['entities'] = {}
29
+ private validateEntities(entities: Model.Schema['entities'], errors: ErrorBuilder): void {
67
30
  for (const [entityName, entity] of Object.entries(entities)) {
68
31
  const entityErrors = errors.for(entityName)
69
- const validEntity = this.validateEntity(entity, entityErrors)
70
- if (!validEntity) {
71
- continue
32
+ if (entity.name !== entityName) {
33
+ entityErrors.add(`Entity name "${entity.name}" does not match the name in a map "${entityName}"`)
72
34
  }
73
- if (validEntity.name !== entityName) {
74
- entityErrors.add(`Entity name "${validEntity.name}" does not match the name in a map "${entityName}"`)
75
- continue
76
- }
77
-
78
- validEntities[entityName] = validEntity
35
+ this.validateEntity(entity, entityErrors)
79
36
  }
80
- return validEntities
81
37
  }
82
38
 
83
- private validateEntity(entity: unknown, errors: ErrorBuilder): Model.Entity | undefined {
84
- if (!isObject(entity)) {
85
- errors.add('Entity must be an object')
86
- return undefined
87
- }
88
- if (typeof entity.name !== 'string') {
89
- errors.for('name').add('Entity name must be a string')
90
- return undefined
91
- }
92
- if (!this.validateIdentifier(entity.name, errors)) {
93
- return undefined
94
- }
95
- if (typeof entity.primary !== 'string') {
96
- errors.for('primary').add('Primary must be a string')
97
- return undefined
98
- }
99
- if (typeof entity.primaryColumn !== 'string') {
100
- errors.for('primaryColumn').add('Primary column must be a string')
101
- return undefined
102
- }
103
- if (typeof entity.tableName !== 'string') {
104
- errors.for('tableName').add('Table name must be a string')
105
- return undefined
106
- }
107
- const fields = entity.fields
108
- if (!isObject(fields)) {
109
- errors.add('Fields must be an object')
110
- return undefined
111
- }
112
- const partialEntity: Model.Entity = {
113
- name: entity.name,
114
- primary: entity.primary,
115
- primaryColumn: entity.primaryColumn,
116
- tableName: entity.tableName,
117
- fields: {},
118
- unique: {},
119
- }
39
+ private validateEntity(entity: Model.Entity, errors: ErrorBuilder): void {
40
+ this.validateIdentifier(entity.name, errors)
120
41
 
121
- if (entity.view) {
122
- const viewTmp = entity.view
123
- if (!isObject(viewTmp)) {
124
- errors.for('view').add('View must be an object')
125
- return undefined
126
- }
127
- if (typeof viewTmp.sql !== 'string') {
128
- errors.for('view', 'sql').add('View SQL must be a string')
129
- return undefined
130
- }
131
- partialEntity.view = entity.view as Model.View
132
- }
133
-
134
- const validFields: Model.Entity['fields'] = {}
135
- for (const [fieldName, field] of Object.entries(fields)) {
42
+ for (const [fieldName, field] of Object.entries(entity.fields)) {
136
43
  const fieldErrors = errors.for(fieldName)
137
- const validField = this.validateField(partialEntity, field, fieldErrors)
138
- if (!validField) {
139
- continue
44
+ this.validateField(entity, field, fieldErrors)
45
+ if (field.name !== fieldName) {
46
+ fieldErrors.add(`Field name "${field.name}" does not match the name in a map "${fieldName}"`)
140
47
  }
141
- if (validField.name !== fieldName) {
142
- fieldErrors.add(`Field name "${validField.name}" does not match the name in a map "${fieldName}"`)
143
- continue
144
- }
145
- validFields[fieldName] = validField
146
- }
147
-
148
- const uniqueConstraints = entity.unique
149
- if (!isObject(uniqueConstraints)) {
150
- errors.add('Unique constraints must be an object')
151
- return undefined
152
48
  }
153
- const validUniqueConstraints = this.validateUniqueConstraints(
154
- uniqueConstraints,
155
- new Set(Object.keys(validFields)),
49
+ this.validateUniqueConstraints(
50
+ entity.unique,
51
+ new Set(Object.keys(entity.fields)),
156
52
  errors.for('unique'),
157
53
  )
158
-
159
- return {
160
- ...partialEntity,
161
- fields: validFields,
162
- unique: validUniqueConstraints,
163
- }
164
54
  }
165
55
 
166
- private validateUniqueConstraints(
167
- uniqueConstraints: unknown,
168
- fields: Set<string>,
169
- errors: ErrorBuilder,
170
- ): Model.Entity['unique'] {
171
- if (!isObject(uniqueConstraints)) {
172
- errors.add('Unique constraints must be an object')
173
- return {}
174
- }
175
- const validUniqueConstraints: Model.Entity['unique'] = {}
176
- constraint: for (const [constraintName, constraint] of Object.entries(uniqueConstraints)) {
56
+ private validateUniqueConstraints(uniqueConstraints: Model.Entity['unique'], fields: Set<string>, errors: ErrorBuilder): void {
57
+ for (const [constraintName, constraint] of Object.entries(uniqueConstraints)) {
177
58
  const uniqueErrors = errors.for(constraintName)
178
- if (!isObject(constraint)) {
179
- uniqueErrors.add('Unique constraint must be an object')
180
- continue
181
- }
182
- if (typeof constraint.name !== 'string') {
183
- uniqueErrors.add('Constraint name is not defined')
184
- continue
185
- }
186
59
  if (constraint.name !== constraintName) {
187
60
  uniqueErrors.add(`Constraint name ${constraint.name} does not match the name in a map "${constraintName}"`)
188
61
  continue
189
62
  }
190
- if (
191
- !Array.isArray(constraint.fields) ||
192
- !everyIs(constraint.fields, (it): it is string => typeof it === 'string')
193
- ) {
194
- uniqueErrors.add('Every field must be a string')
195
- continue
196
- }
197
63
  for (const field of constraint.fields) {
198
64
  if (!fields.has(field)) {
199
65
  uniqueErrors.add(`Referenced field ${field} in a constraint does not exists`)
200
- continue constraint
201
66
  }
202
67
  }
203
- validUniqueConstraints[constraintName] = { name: constraint.name, fields: constraint.fields }
204
68
  }
205
- return validUniqueConstraints
206
69
  }
207
70
 
208
- private validateField(partialEntity: Model.Entity, field: unknown, errors: ErrorBuilder): Model.AnyField | undefined {
209
- if (!isObject(field)) {
210
- errors.add('Field must be an object')
211
- return undefined
71
+ private validateField(partialEntity: Model.Entity, field: Model.AnyField, errors: ErrorBuilder): void {
72
+ this.validateIdentifier(field.name, errors)
73
+ if (isRelation(field)) {
74
+ this.validateRelation(partialEntity, field, errors)
212
75
  }
213
- if (typeof field.type !== 'string') {
214
- errors.add('Field type must be a string')
215
- return undefined
216
- }
217
- if (typeof field.name !== 'string') {
218
- errors.for('name').add('Field name must be a string')
219
- return undefined
220
- }
221
- if (!this.validateIdentifier(field.name, errors)) {
222
- return undefined
223
- }
224
- if (isRelation(field as any)) {
225
- return this.validateRelation(partialEntity, field, errors)
226
- }
227
- return field as unknown as Model.AnyColumn
228
76
  }
229
77
 
230
- private validateRelation(
231
- partialEntity: Model.Entity,
232
- field: UnknownObject,
233
- errors: ErrorBuilder,
234
- ): Model.AnyRelation | undefined {
78
+ private validateRelation(partialEntity: Model.Entity, field: Model.AnyRelation, errors: ErrorBuilder): void {
235
79
  const entityName = partialEntity.name
236
- const targetEntityName = field.target as string // todo
80
+ const targetEntityName = field.target
237
81
  const targetEntity = this.model.entities[targetEntityName] || undefined
238
82
  if (!targetEntity) {
239
- errors.add(`Target entity ${targetEntityName} not found`)
240
- return undefined
83
+ return errors.add(`Target entity ${targetEntityName} not found`)
241
84
  }
242
- if (((it: Model.AnyRelation): it is Model.AnyRelation & Model.OrderableRelation => 'orderBy' in it)(field as any)) {
85
+ if (((it: Model.AnyRelation): it is Model.AnyRelation & Model.OrderableRelation => 'orderBy' in it)(field)) {
243
86
  (field as Model.OrderableRelation).orderBy?.forEach(it => {
244
87
  let entity = targetEntity
245
88
 
@@ -262,133 +105,95 @@ export class ModelValidator {
262
105
  })
263
106
  }
264
107
  if (partialEntity.view) {
265
- const type = (field as any as Model.Relation).type
266
108
  if (
267
- type === Model.RelationType.ManyHasMany ||
268
- type === Model.RelationType.OneHasMany ||
269
- (type === Model.RelationType.OneHasOne && !('joiningColumn' in field))
109
+ field.type === Model.RelationType.ManyHasMany ||
110
+ field.type === Model.RelationType.OneHasMany ||
111
+ (field.type === Model.RelationType.OneHasOne && !('joiningColumn' in field))
270
112
  ) {
271
- errors.add(
272
- 'This relation type is not allowed on a view entity. Only one-has-one owning and many-has one are allowed.',
273
- )
113
+ return errors.add('This relation type is not allowed on a view entity. Only one-has-one owning and many-has one are allowed.')
274
114
  }
275
115
  }
276
- if (isInverseRelation(field as any as Model.Relation)) {
277
- // todo
116
+ if (isInverseRelation(field)) {
278
117
  const ownedBy = field.ownedBy
279
- if (typeof ownedBy !== 'string') {
280
- errors.add('Owned by is not defined')
281
- return undefined
282
- }
283
118
  const targetField = targetEntity.fields[ownedBy]
284
119
  const relationDescription = `Target relation ${targetEntityName}::${ownedBy}:`
285
120
  if (!targetField) {
286
- errors.add(`${relationDescription} not exists`)
287
- return undefined
121
+ return errors.add(`${relationDescription} not exists`)
288
122
  }
123
+
289
124
  if (!isRelation(targetField)) {
290
- errors.add(`${relationDescription} not a relation`)
291
- return undefined
125
+ return errors.add(`${relationDescription} not a relation`)
292
126
  }
293
127
  if (targetField.target !== entityName) {
294
- errors.add(
295
- `${relationDescription} back reference to entity ${entityName} expected, but ${targetField.target} given`,
296
- )
297
- return undefined
128
+ return errors.add(`${relationDescription} back reference to entity ${entityName} expected, but ${targetField.target} given`)
298
129
  }
299
130
  if (!isOwningRelation(targetField)) {
300
131
  errors.add(`${relationDescription} not an owning relation`)
301
- return undefined
132
+ return
302
133
  }
303
134
  if (!targetField.inversedBy) {
304
- errors.add(`${relationDescription} inverse relation is not set`)
305
- return undefined
135
+ return errors.add(`${relationDescription} inverse relation is not set`)
306
136
  }
307
137
  if (targetField.inversedBy !== field.name) {
308
- errors.add(
309
- `${relationDescription} back reference ${entityName}::${field.name} exepcted, ${targetField.target}::${targetField.inversedBy} given`,
310
- )
311
- return undefined
138
+ return errors.add(`${relationDescription} back reference ${entityName}::${field.name} exepcted, ${targetField.target}::${targetField.inversedBy} given`)
312
139
  }
313
140
  if (field.type === Model.RelationType.OneHasOne && targetField.type !== Model.RelationType.OneHasOne) {
314
- errors.add(`${relationDescription} "OneHasOne" type expected, "${targetField.type}" given`)
315
- return undefined
141
+ return errors.add(`${relationDescription} "OneHasOne" type expected, "${targetField.type}" given`)
316
142
  }
317
143
  if (field.type === Model.RelationType.OneHasMany && targetField.type !== Model.RelationType.ManyHasOne) {
318
- errors.add(`${relationDescription} "ManyHasOne" type expected, "${targetField.type}" given`)
319
- return undefined
144
+ return errors.add(`${relationDescription} "ManyHasOne" type expected, "${targetField.type}" given`)
320
145
  }
321
146
  if (field.type === Model.RelationType.ManyHasMany && targetField.type !== Model.RelationType.ManyHasMany) {
322
- errors.add(`${relationDescription} "ManyHasMany" type expected, "${targetField.type}" given`)
323
- return undefined
147
+ return errors.add(`${relationDescription} "ManyHasMany" type expected, "${targetField.type}" given`)
324
148
  }
325
149
  } else {
326
- const inversedBy = field.inversedBy as string // todo
150
+ const inversedBy = field.inversedBy
327
151
  if (targetEntity.view) {
328
152
  if ('joiningColumn' in field) {
329
- errors.add(
330
- `View entity ${targetEntity.name} cannot be referenced from an owning relation. Try switching the owning side.`,
331
- )
153
+ return errors.add(`View entity ${targetEntity.name} cannot be referenced from an owning relation. Try switching the owning side.`)
332
154
  }
333
155
  }
334
156
  if (inversedBy) {
335
157
  const targetField = targetEntity.fields[inversedBy]
336
158
  const relationDescription = `Target relation ${targetEntityName}::${inversedBy}:`
337
159
  if (!targetField) {
338
- errors.add(`${relationDescription} not exists`)
339
- return undefined
160
+ return errors.add(`${relationDescription} not exists`)
340
161
  }
341
162
  if (!isRelation(targetField)) {
342
- errors.add(`${relationDescription} not a relation`)
343
- return undefined
163
+ return errors.add(`${relationDescription} not a relation`)
344
164
  }
345
165
  if (targetField.target !== entityName) {
346
- errors.add(
347
- `${relationDescription} back reference to entity ${entityName} expected, but ${targetField.target} given`,
348
- )
349
- return undefined
166
+ return errors.add(`${relationDescription} back reference to entity ${entityName} expected, but ${targetField.target} given`)
350
167
  }
351
168
  if (!isInverseRelation(targetField)) {
352
- errors.add(`${relationDescription} not an inverse relation`)
353
- return undefined
169
+ return errors.add(`${relationDescription} not an inverse relation`)
354
170
  }
355
171
  if (!targetField.ownedBy) {
356
- errors.add(`${relationDescription} owning relation is not set`)
357
- return undefined
172
+ return errors.add(`${relationDescription} owning relation is not set`)
358
173
  }
359
174
  if (targetField.ownedBy !== field.name) {
360
- errors.add(
361
- `${relationDescription} back reference ${entityName}::${field.name} exepcted, ${targetField.target}::${targetField.ownedBy} given`,
362
- )
363
- return undefined
175
+ return errors.add(`${relationDescription} back reference ${entityName}::${field.name} exepcted, ${targetField.target}::${targetField.ownedBy} given`)
364
176
  }
365
177
  if (field.type === Model.RelationType.OneHasOne && targetField.type !== Model.RelationType.OneHasOne) {
366
- errors.add(`${relationDescription} "OneHasOne" type expected, "${targetField.type}" given`)
367
- return undefined
178
+ return errors.add(`${relationDescription} "OneHasOne" type expected, "${targetField.type}" given`)
368
179
  }
369
180
  if (field.type === Model.RelationType.ManyHasOne && targetField.type !== Model.RelationType.OneHasMany) {
370
- errors.add(`${relationDescription} "ManyHasOne" type expected, "${targetField.type}" given`)
371
- return undefined
181
+ return errors.add(`${relationDescription} "ManyHasOne" type expected, "${targetField.type}" given`)
372
182
  }
373
183
  if (field.type === Model.RelationType.ManyHasMany && targetField.type !== Model.RelationType.ManyHasMany) {
374
- errors.add(`${relationDescription} "ManyHasMany" type expected, "${targetField.type}" given`)
375
- return undefined
184
+ return errors.add(`${relationDescription} "ManyHasMany" type expected, "${targetField.type}" given`)
376
185
  }
377
186
  }
378
187
  }
379
- return field as any as Model.AnyRelation // todo
380
188
  }
381
189
 
382
190
  private validateIdentifier(value: string, errorBuilder: ErrorBuilder) {
383
191
  if (!value.match(IDENTIFIER_PATTERN)) {
384
- errorBuilder.add(`${value} must match pattern ${IDENTIFIER_PATTERN.source}`)
385
- return false
192
+ return errorBuilder.add(`${value} must match pattern ${IDENTIFIER_PATTERN.source}`)
386
193
  }
387
194
  if (RESERVED_WORDS.includes(value)) {
388
195
  errorBuilder.add(`${value} is reserved word`)
389
- return false
390
196
  }
391
- return true
392
197
  }
393
198
 
394
199
  private validateCollisions(entities: Model.Entity[], errorBuilder: ErrorBuilder) {
@@ -399,11 +204,7 @@ export class ModelValidator {
399
204
  if (tableNames[entity.tableName]) {
400
205
  errorBuilder
401
206
  .for(entity.name)
402
- .add(
403
- `Table name ${entity.tableName} of ${description} collides with a table name of ${
404
- tableNames[entity.tableName]
405
- }`,
406
- )
207
+ .add(`Table name ${entity.tableName} of ${description} collides with a table name of ${tableNames[entity.tableName]}`)
407
208
  } else {
408
209
  tableNames[entity.tableName] = description
409
210
  }
@@ -418,9 +219,8 @@ export class ModelValidator {
418
219
  entityErrorBuilder
419
220
  .for(relation.name)
420
221
  .add(
421
- `Joining table name ${joiningTable.tableName} of ${description} collides with a table name of ${
422
- tableNames[joiningTable.tableName]
423
- }. Consider using plural for a relation name or change the joining table name using .joiningTable(...) in schema definition.`,
222
+ `Joining table name ${joiningTable.tableName} of ${description} collides with a table name of ${tableNames[joiningTable.tableName]}.` +
223
+ 'Consider using plural for a relation name or change the joining table name using .joiningTable(...) in schema definition.',
424
224
  )
425
225
  } else {
426
226
  tableNames[joiningTable.tableName] = description
@@ -2,33 +2,20 @@ import { Schema } from '@contember/schema'
2
2
  import { ValidationError } from './errors'
3
3
  import { AclValidator } from './AclValidator'
4
4
  import { ModelValidator } from './ModelValidator'
5
- import { isDeepStrictEqual } from 'util'
6
5
  import { ValidationValidator } from './ValidationValidator'
7
- import { deepCompare } from '../utils'
8
6
 
9
7
  export class SchemaValidator {
10
8
  public static validate(schema: Schema): ValidationError[] {
9
+ const modelValidator = new ModelValidator(schema.model)
10
+ const modelErrors = modelValidator.validate()
11
+
11
12
  const aclValidator = new AclValidator(schema.model)
12
- const [acl, aclErrors] = aclValidator.validate(schema.acl)
13
+ const aclErrors = aclValidator.validate(schema.acl)
13
14
 
14
- const modelValidator = new ModelValidator(schema.model)
15
- const [model, modelErrors] = modelValidator.validate()
16
15
 
17
16
  const validationValidator = new ValidationValidator(schema.model)
18
- const [validation, validationErrors] = validationValidator.validate(schema.validation)
19
-
20
- const validSchema = { ...schema, acl, model, validation }
17
+ const validationErrors = validationValidator.validate(schema.validation)
21
18
 
22
- const errors = [...aclErrors, ...modelErrors, ...validationErrors]
23
- if (errors.length === 0 && !isDeepStrictEqual(validSchema, schema)) {
24
- const errors = deepCompare(validSchema, schema, [])
25
- let message = 'There is something wrong with a schema validator:'
26
- for (const err of errors) {
27
- message += '\n\t' + err.path.join('.') + ': ' + err.message
28
- }
29
- message += '\n\nPlease fill a bug report'
30
- throw new Error(message)
31
- }
32
- return errors
19
+ return [...aclErrors, ...modelErrors, ...validationErrors]
33
20
  }
34
21
  }