@contember/schema-utils
Advanced tools
Comparing version 0.10.0-alpha.2 to 0.10.0-alpha.3
@@ -23,5 +23,5 @@ import { Model } from '@contember/schema'; | ||
export declare const isRelation: (field: Model.AnyField) => field is Model.AnyRelation; | ||
export declare const isInversedRelation: (relation: Model.Relation) => relation is Model.InversedRelation; | ||
export declare const isOwnerRelation: (relation: Model.Relation) => relation is Model.OwnerRelation; | ||
export declare const isInverseRelation: (relation: Model.Relation) => relation is Model.InverseRelation; | ||
export declare const isOwningRelation: (relation: Model.Relation) => relation is Model.OwningRelation; | ||
export declare const emptyModelSchema: Model.Schema; | ||
//# sourceMappingURL=modelUtils.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.emptyModelSchema = exports.isOwnerRelation = exports.isInversedRelation = exports.isRelation = exports.acceptRelationTypeVisitor = exports.acceptFieldVisitor = exports.acceptEveryFieldVisitor = exports.getTargetEntity = exports.getColumnType = exports.tryGetColumnName = exports.getColumnName = exports.getEntity = exports.ModelError = exports.ModelErrorCode = void 0; | ||
exports.emptyModelSchema = exports.isOwningRelation = exports.isInverseRelation = exports.isRelation = exports.acceptRelationTypeVisitor = exports.acceptFieldVisitor = exports.acceptEveryFieldVisitor = exports.getTargetEntity = exports.getColumnType = exports.tryGetColumnName = exports.getColumnName = exports.getEntity = exports.ModelError = exports.ModelErrorCode = void 0; | ||
const utils_1 = require("../utils"); | ||
@@ -98,6 +98,6 @@ const schema_1 = require("@contember/schema"); | ||
let targetRelation = null; | ||
if (exports.isOwnerRelation(fieldObj)) { | ||
if (exports.isOwningRelation(fieldObj)) { | ||
targetRelation = fieldObj.inversedBy ? targetEntity.fields[fieldObj.inversedBy] || null : null; | ||
} | ||
else if (exports.isInversedRelation(fieldObj)) { | ||
else if (exports.isInverseRelation(fieldObj)) { | ||
targetRelation = targetEntity.fields[fieldObj.ownedBy]; | ||
@@ -115,11 +115,11 @@ } | ||
return exports.acceptRelationTypeVisitor(schema, entityObj, fieldObj, { | ||
visitManyHasManyInversed: visitor.visitHasMany.bind(visitor), | ||
visitManyHasManyOwner: visitor.visitHasMany.bind(visitor), | ||
visitManyHasManyInverse: visitor.visitHasMany.bind(visitor), | ||
visitManyHasManyOwning: visitor.visitHasMany.bind(visitor), | ||
visitOneHasMany: visitor.visitHasMany.bind(visitor), | ||
visitOneHasOneInversed: visitor.visitHasOne.bind(visitor), | ||
visitOneHasOneOwner: visitor.visitHasOne.bind(visitor), | ||
visitOneHasOneInverse: visitor.visitHasOne.bind(visitor), | ||
visitOneHasOneOwning: visitor.visitHasOne.bind(visitor), | ||
visitManyHasOne: visitor.visitHasOne.bind(visitor), | ||
}); | ||
} | ||
if (utils_1.isIt(visitor, 'visitManyHasManyInversed')) { | ||
if (utils_1.isIt(visitor, 'visitManyHasManyInverse')) { | ||
return exports.acceptRelationTypeVisitor(schema, entityObj, fieldObj, visitor); | ||
@@ -142,3 +142,3 @@ } | ||
const targetEntity = exports.getEntity(schema, relationObj.target); | ||
if (exports.isInversedRelation(relationObj)) { | ||
if (exports.isInverseRelation(relationObj)) { | ||
const targetRelation = targetEntity.fields[relationObj.ownedBy]; | ||
@@ -150,7 +150,8 @@ if (!exports.isRelation(targetRelation)) { | ||
case schema_1.Model.RelationType.ManyHasMany: | ||
return visitor.visitManyHasManyInversed(entityObj, relationObj, targetEntity, targetRelation); | ||
return visitor.visitManyHasManyInverse(entityObj, relationObj, targetEntity, targetRelation); | ||
case schema_1.Model.RelationType.OneHasOne: | ||
return visitor.visitOneHasOneInversed(entityObj, relationObj, targetEntity, targetRelation); | ||
return visitor.visitOneHasOneInverse(entityObj, relationObj, targetEntity, targetRelation); | ||
case schema_1.Model.RelationType.OneHasMany: | ||
return visitor.visitOneHasMany(entityObj, relationObj, targetEntity, targetRelation); | ||
return visitor.visitOneHasMany(entityObj, // | ||
relationObj, targetEntity, targetRelation); | ||
default: | ||
@@ -160,11 +161,12 @@ return utils_1.assertNever(relationObj); | ||
} | ||
else if (exports.isOwnerRelation(relationObj)) { | ||
else if (exports.isOwningRelation(relationObj)) { | ||
const targetRelation = relationObj.inversedBy ? targetEntity.fields[relationObj.inversedBy] : null; | ||
switch (relationObj.type) { | ||
case schema_1.Model.RelationType.ManyHasMany: | ||
return visitor.visitManyHasManyOwner(entityObj, relationObj, targetEntity, targetRelation); | ||
return visitor.visitManyHasManyOwning(entityObj, relationObj, targetEntity, targetRelation); | ||
case schema_1.Model.RelationType.OneHasOne: | ||
return visitor.visitOneHasOneOwner(entityObj, relationObj, targetEntity, targetRelation); | ||
return visitor.visitOneHasOneOwning(entityObj, relationObj, targetEntity, targetRelation); | ||
case schema_1.Model.RelationType.ManyHasOne: | ||
return visitor.visitManyHasOne(entityObj, relationObj, targetEntity, targetRelation); | ||
return visitor.visitManyHasOne(entityObj, // | ||
relationObj, targetEntity, targetRelation); | ||
default: | ||
@@ -179,9 +181,9 @@ return utils_1.assertNever(relationObj); | ||
}; | ||
exports.isInversedRelation = (relation) => { | ||
exports.isInverseRelation = (relation) => { | ||
return relation.ownedBy !== undefined; | ||
}; | ||
exports.isOwnerRelation = (relation) => { | ||
return !exports.isInversedRelation(relation); | ||
exports.isOwningRelation = (relation) => { | ||
return !exports.isInverseRelation(relation); | ||
}; | ||
exports.emptyModelSchema = { entities: {}, enums: {} }; | ||
//# sourceMappingURL=modelUtils.js.map |
@@ -13,3 +13,4 @@ import { Model } from '@contember/schema'; | ||
private validateRelation; | ||
private validateIdentifier; | ||
} | ||
//# sourceMappingURL=ModelValidator.d.ts.map |
@@ -8,2 +8,4 @@ "use strict"; | ||
const model_1 = require("../model"); | ||
const IDENTIFIER_PATTERN = /^[_a-zA-Z][_a-zA-Z0-9]*$/; | ||
const RESERVED_WORDS = ['and', 'or', 'not']; | ||
class ModelValidator { | ||
@@ -38,3 +40,3 @@ constructor(model) { | ||
const validEnums = {}; | ||
for (const [enumName, enumValues] of Object.entries(enums)) { | ||
enums: for (const [enumName, enumValues] of Object.entries(enums)) { | ||
if (!Array.isArray(enumValues) || !utils_1.everyIs(enumValues, (it) => typeof it === 'string')) { | ||
@@ -44,2 +46,8 @@ errors.for(enumName).add('Enum values must be an array of strings'); | ||
} | ||
for (const value of enumValues) { | ||
const valueErrors = errors.for(value); | ||
if (!this.validateIdentifier(value, valueErrors)) { | ||
continue enums; | ||
} | ||
} | ||
validEnums[enumName] = enumValues; | ||
@@ -82,2 +90,5 @@ } | ||
} | ||
if (!this.validateIdentifier(entity.name, errors)) { | ||
return undefined; | ||
} | ||
if (typeof entity.primary !== 'string') { | ||
@@ -172,2 +183,9 @@ errors.for('primary').add('Primary must be a string'); | ||
} | ||
if (typeof field.name !== 'string') { | ||
errors.for('name').add('Field name must be a string'); | ||
return undefined; | ||
} | ||
if (!this.validateIdentifier(field.name, errors)) { | ||
return undefined; | ||
} | ||
if (isRelation(field)) { | ||
@@ -208,3 +226,3 @@ return this.validateRelation(entityName, field, errors); | ||
} | ||
if (model_1.isInversedRelation(field)) { | ||
if (model_1.isInverseRelation(field)) { | ||
// todo | ||
@@ -230,8 +248,8 @@ const ownedBy = field.ownedBy; | ||
} | ||
if (!model_1.isOwnerRelation(targetField)) { | ||
errors.add(`${relationDescription} not an owner relation`); | ||
if (!model_1.isOwningRelation(targetField)) { | ||
errors.add(`${relationDescription} not an owning relation`); | ||
return undefined; | ||
} | ||
if (!targetField.inversedBy) { | ||
errors.add(`${relationDescription} inversed relation is not set`); | ||
errors.add(`${relationDescription} inverse relation is not set`); | ||
return undefined; | ||
@@ -273,4 +291,4 @@ } | ||
} | ||
if (!model_1.isInversedRelation(targetField)) { | ||
errors.add(`${relationDescription} not an inversed relation`); | ||
if (!model_1.isInverseRelation(targetField)) { | ||
errors.add(`${relationDescription} not an inverse relation`); | ||
return undefined; | ||
@@ -302,2 +320,13 @@ } | ||
} | ||
validateIdentifier(value, errorBuilder) { | ||
if (!value.match(IDENTIFIER_PATTERN)) { | ||
errorBuilder.add(`${value} must match pattern ${IDENTIFIER_PATTERN.source}`); | ||
return false; | ||
} | ||
if (RESERVED_WORDS.includes(value)) { | ||
errorBuilder.add(`${value} is reserved word`); | ||
return false; | ||
} | ||
return true; | ||
} | ||
} | ||
@@ -304,0 +333,0 @@ exports.ModelValidator = ModelValidator; |
{ | ||
"name": "@contember/schema-utils", | ||
"version": "0.10.0-alpha.2", | ||
"version": "0.10.0-alpha.3", | ||
"license": "Apache-2.0", | ||
@@ -11,3 +11,3 @@ "main": "dist/src/index.js", | ||
"dependencies": { | ||
"@contember/schema": "^0.10.0-alpha.2" | ||
"@contember/schema": "^0.10.0-alpha.3" | ||
}, | ||
@@ -14,0 +14,0 @@ "devDependencies": { |
@@ -124,5 +124,5 @@ import { assertNever, isIt } from '../utils' | ||
let targetRelation = null | ||
if (isOwnerRelation(fieldObj)) { | ||
if (isOwningRelation(fieldObj)) { | ||
targetRelation = fieldObj.inversedBy ? targetEntity.fields[fieldObj.inversedBy] || null : null | ||
} else if (isInversedRelation(fieldObj)) { | ||
} else if (isInverseRelation(fieldObj)) { | ||
targetRelation = targetEntity.fields[fieldObj.ownedBy] | ||
@@ -140,7 +140,7 @@ } else { | ||
return acceptRelationTypeVisitor(schema, entityObj, fieldObj, { | ||
visitManyHasManyInversed: visitor.visitHasMany.bind(visitor), | ||
visitManyHasManyOwner: visitor.visitHasMany.bind(visitor), | ||
visitManyHasManyInverse: visitor.visitHasMany.bind(visitor), | ||
visitManyHasManyOwning: visitor.visitHasMany.bind(visitor), | ||
visitOneHasMany: visitor.visitHasMany.bind(visitor), | ||
visitOneHasOneInversed: visitor.visitHasOne.bind(visitor), | ||
visitOneHasOneOwner: visitor.visitHasOne.bind(visitor), | ||
visitOneHasOneInverse: visitor.visitHasOne.bind(visitor), | ||
visitOneHasOneOwning: visitor.visitHasOne.bind(visitor), | ||
visitManyHasOne: visitor.visitHasOne.bind(visitor), | ||
@@ -150,3 +150,3 @@ }) | ||
if (isIt<Model.ColumnVisitor<T> & Model.RelationByTypeVisitor<T>>(visitor, 'visitManyHasManyInversed')) { | ||
if (isIt<Model.ColumnVisitor<T> & Model.RelationByTypeVisitor<T>>(visitor, 'visitManyHasManyInverse')) { | ||
return acceptRelationTypeVisitor(schema, entityObj, fieldObj, visitor) | ||
@@ -179,3 +179,3 @@ } | ||
if (isInversedRelation(relationObj)) { | ||
if (isInverseRelation(relationObj)) { | ||
const targetRelation = targetEntity.fields[relationObj.ownedBy] | ||
@@ -187,19 +187,19 @@ if (!isRelation(targetRelation)) { | ||
case Model.RelationType.ManyHasMany: | ||
return visitor.visitManyHasManyInversed( | ||
return visitor.visitManyHasManyInverse( | ||
entityObj, | ||
relationObj as Model.ManyHasManyInversedRelation, | ||
relationObj, | ||
targetEntity, | ||
targetRelation as Model.ManyHasManyOwnerRelation, | ||
targetRelation as Model.ManyHasManyOwningRelation, | ||
) | ||
case Model.RelationType.OneHasOne: | ||
return visitor.visitOneHasOneInversed( | ||
return visitor.visitOneHasOneInverse( | ||
entityObj, | ||
relationObj as Model.OneHasOneInversedRelation, | ||
relationObj, | ||
targetEntity, | ||
targetRelation as Model.OneHasOneOwnerRelation, | ||
targetRelation as Model.OneHasOneOwningRelation, | ||
) | ||
case Model.RelationType.OneHasMany: | ||
return visitor.visitOneHasMany( | ||
entityObj, | ||
relationObj as Model.OneHasManyRelation, | ||
entityObj, // | ||
relationObj, | ||
targetEntity, | ||
@@ -211,3 +211,3 @@ targetRelation as Model.ManyHasOneRelation, | ||
} | ||
} else if (isOwnerRelation(relationObj)) { | ||
} else if (isOwningRelation(relationObj)) { | ||
const targetRelation = relationObj.inversedBy ? targetEntity.fields[relationObj.inversedBy] : null | ||
@@ -217,19 +217,19 @@ | ||
case Model.RelationType.ManyHasMany: | ||
return visitor.visitManyHasManyOwner( | ||
return visitor.visitManyHasManyOwning( | ||
entityObj, | ||
relationObj as Model.ManyHasManyOwnerRelation, | ||
relationObj, | ||
targetEntity, | ||
targetRelation as Model.ManyHasManyInversedRelation, | ||
targetRelation as Model.ManyHasManyInverseRelation, | ||
) | ||
case Model.RelationType.OneHasOne: | ||
return visitor.visitOneHasOneOwner( | ||
return visitor.visitOneHasOneOwning( | ||
entityObj, | ||
relationObj as Model.OneHasOneOwnerRelation, | ||
relationObj, | ||
targetEntity, | ||
targetRelation as Model.OneHasOneInversedRelation, | ||
targetRelation as Model.OneHasOneInverseRelation, | ||
) | ||
case Model.RelationType.ManyHasOne: | ||
return visitor.visitManyHasOne( | ||
entityObj, | ||
relationObj as Model.ManyHasOneRelation, | ||
entityObj, // | ||
relationObj, | ||
targetEntity, | ||
@@ -250,10 +250,10 @@ targetRelation as Model.OneHasManyRelation, | ||
export const isInversedRelation = (relation: Model.Relation): relation is Model.InversedRelation => { | ||
return (relation as Model.InversedRelation).ownedBy !== undefined | ||
export const isInverseRelation = (relation: Model.Relation): relation is Model.InverseRelation => { | ||
return (relation as Model.InverseRelation).ownedBy !== undefined | ||
} | ||
export const isOwnerRelation = (relation: Model.Relation): relation is Model.OwnerRelation => { | ||
return !isInversedRelation(relation) | ||
export const isOwningRelation = (relation: Model.Relation): relation is Model.OwningRelation => { | ||
return !isInverseRelation(relation) | ||
} | ||
export const emptyModelSchema: Model.Schema = { entities: {}, enums: {} } |
import { Model } from '@contember/schema' | ||
import { ErrorBuilder, ValidationError } from './errors' | ||
import { everyIs, isObject, UnknownObject } from './utils' | ||
import { getTargetEntity, isInversedRelation, isOwnerRelation } from '../model' | ||
import { getTargetEntity, isInverseRelation, isOwningRelation } from '../model' | ||
const IDENTIFIER_PATTERN = /^[_a-zA-Z][_a-zA-Z0-9]*$/ | ||
const RESERVED_WORDS = ['and', 'or', 'not'] | ||
export class ModelValidator { | ||
@@ -34,3 +37,3 @@ constructor(private readonly model: Model.Schema) {} | ||
const validEnums: Model.Schema['enums'] = {} | ||
for (const [enumName, enumValues] of Object.entries(enums)) { | ||
enums: for (const [enumName, enumValues] of Object.entries(enums)) { | ||
if (!Array.isArray(enumValues) || !everyIs(enumValues, (it): it is string => typeof it === 'string')) { | ||
@@ -40,2 +43,8 @@ errors.for(enumName).add('Enum values must be an array of strings') | ||
} | ||
for (const value of enumValues) { | ||
const valueErrors = errors.for(value) | ||
if (!this.validateIdentifier(value, valueErrors)) { | ||
continue enums | ||
} | ||
} | ||
validEnums[enumName] = enumValues | ||
@@ -81,2 +90,5 @@ } | ||
} | ||
if (!this.validateIdentifier(entity.name, errors)) { | ||
return undefined | ||
} | ||
if (typeof entity.primary !== 'string') { | ||
@@ -186,2 +198,9 @@ errors.for('primary').add('Primary must be a string') | ||
} | ||
if (typeof field.name !== 'string') { | ||
errors.for('name').add('Field name must be a string') | ||
return undefined | ||
} | ||
if (!this.validateIdentifier(field.name, errors)) { | ||
return undefined | ||
} | ||
if (isRelation(field as any)) { | ||
@@ -226,3 +245,3 @@ return this.validateRelation(entityName, field, errors) | ||
} | ||
if (isInversedRelation((field as any) as Model.Relation)) { | ||
if (isInverseRelation((field as any) as Model.Relation)) { | ||
// todo | ||
@@ -250,8 +269,8 @@ const ownedBy = field.ownedBy | ||
} | ||
if (!isOwnerRelation(targetField)) { | ||
errors.add(`${relationDescription} not an owner relation`) | ||
if (!isOwningRelation(targetField)) { | ||
errors.add(`${relationDescription} not an owning relation`) | ||
return undefined | ||
} | ||
if (!targetField.inversedBy) { | ||
errors.add(`${relationDescription} inversed relation is not set`) | ||
errors.add(`${relationDescription} inverse relation is not set`) | ||
return undefined | ||
@@ -296,4 +315,4 @@ } | ||
} | ||
if (!isInversedRelation(targetField)) { | ||
errors.add(`${relationDescription} not an inversed relation`) | ||
if (!isInverseRelation(targetField)) { | ||
errors.add(`${relationDescription} not an inverse relation`) | ||
return undefined | ||
@@ -327,2 +346,14 @@ } | ||
} | ||
private validateIdentifier(value: string, errorBuilder: ErrorBuilder) { | ||
if (!value.match(IDENTIFIER_PATTERN)) { | ||
errorBuilder.add(`${value} must match pattern ${IDENTIFIER_PATTERN.source}`) | ||
return false | ||
} | ||
if (RESERVED_WORDS.includes(value)) { | ||
errorBuilder.add(`${value} is reserved word`) | ||
return false | ||
} | ||
return true | ||
} | ||
} | ||
@@ -329,0 +360,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
421956
847
3556
3
48