Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@contember/schema-utils

Package Overview
Dependencies
Maintainers
5
Versions
264
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@contember/schema-utils - npm Package Compare versions

Comparing version 0.12.0-alpha.2 to 0.12.0-alpha.4

1

dist/src/model/modelUtils.d.ts

@@ -25,3 +25,4 @@ import { Model } from '@contember/schema';

export declare const isOwningRelation: (relation: Model.Relation) => relation is Model.OwningRelation;
export declare const isColumn: (field: Model.AnyField) => field is Model.AnyColumn<Model.ColumnType>;
export declare const emptyModelSchema: Model.Schema;
//# sourceMappingURL=modelUtils.d.ts.map

4

dist/src/model/modelUtils.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
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;
exports.emptyModelSchema = exports.isColumn = 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");

@@ -193,3 +193,5 @@ const schema_1 = require("@contember/schema");

exports.isOwningRelation = isOwningRelation;
const isColumn = (field) => utils_1.isIt(field, 'columnType');
exports.isColumn = isColumn;
exports.emptyModelSchema = { entities: {}, enums: {} };
//# sourceMappingURL=modelUtils.js.map

@@ -7,27 +7,31 @@ "use strict";

const normalizeSchema = (schema) => {
if (!schema.acl.roles[schema_1.ProjectRole.ADMIN]) {
schema = {
...schema,
acl: {
...schema.acl,
roles: {
...schema.acl.roles,
[schema_1.ProjectRole.ADMIN]: {
stages: '*',
variables: {},
entities: new acl_1.AllowAllPermissionFactory().create(schema.model),
s3: {
'**': {
upload: true,
read: true,
},
var _a;
return {
...schema,
acl: {
...schema.acl,
roles: {
...schema.acl.roles,
[schema_1.ProjectRole.ADMIN]: {
stages: '*',
variables: {},
entities: new acl_1.AllowAllPermissionFactory().create(schema.model),
s3: {
'**': {
upload: true,
read: true,
},
},
...(((_a = schema.acl.roles) === null || _a === void 0 ? void 0 : _a[schema_1.ProjectRole.ADMIN]) || {}),
},
[schema_1.ProjectRole.MIGRATION]: {
stages: '*',
entities: {},
variables: {},
},
},
};
}
return schema;
},
};
};
exports.normalizeSchema = normalizeSchema;
//# sourceMappingURL=schemaNormalizer.js.map

@@ -43,3 +43,3 @@ "use strict";

// }
const rolePermissions = this.validateRolePermissions(roles[role], validRoles, errorBuilder.for(role));
const rolePermissions = this.validateRolePermissions(roles[role], Object.keys(roles), errorBuilder.for(role));
if (rolePermissions !== undefined) {

@@ -79,6 +79,5 @@ validRoles[role] = rolePermissions;

for (const inheritsFrom of inherits) {
if (!roles[inheritsFrom]) {
errorBuilder
.for(inheritsFrom)
.add('Referenced role not exists. Make sure you are defining roles in a right order');
if (!roles.includes(inheritsFrom)) {
// todo: check recursion
errorBuilder.for(inheritsFrom).add('Referenced role not exists.');
}

@@ -85,0 +84,0 @@ else {

@@ -100,3 +100,3 @@ "use strict";

if (typeof entity.tableName !== 'string') {
errors.for('tableName').add('Entity name must be a string');
errors.for('tableName').add('Table name must be a string');
return undefined;

@@ -109,6 +109,26 @@ }

}
const partialEntity = {
name: entity.name,
primary: entity.primary,
primaryColumn: entity.primaryColumn,
tableName: entity.tableName,
fields: {},
unique: {},
};
if (entity.view) {
const viewTmp = entity.view;
if (!utils_1.isObject(viewTmp)) {
errors.for('view').add('View must be an object');
return undefined;
}
if (typeof viewTmp.sql !== 'string') {
errors.for('view', 'sql').add('View SQL must be a string');
return undefined;
}
partialEntity.view = entity.view;
}
const validFields = {};
for (const [fieldName, field] of Object.entries(fields)) {
const fieldErrors = errors.for(fieldName);
const validField = this.validateField(entity.name, field, fieldErrors);
const validField = this.validateField(partialEntity, field, fieldErrors);
if (!validField) {

@@ -130,6 +150,3 @@ continue;

return {
name: entity.name,
primary: entity.primary,
primaryColumn: entity.primaryColumn,
tableName: entity.tableName,
...partialEntity,
fields: validFields,

@@ -174,3 +191,3 @@ unique: validUniqueConstraints,

}
validateField(entityName, field, errors) {
validateField(partialEntity, field, errors) {
if (!utils_1.isObject(field)) {

@@ -192,8 +209,9 @@ errors.add('Field must be an object');

if (isRelation(field)) {
return this.validateRelation(entityName, field, errors);
return this.validateRelation(partialEntity, field, errors);
}
return field;
}
validateRelation(entityName, field, errors) {
validateRelation(partialEntity, field, errors) {
var _a;
const entityName = partialEntity.name;
const targetEntityName = field.target; // todo

@@ -227,2 +245,10 @@ const targetEntity = this.model.entities[targetEntityName] || undefined;

}
if (partialEntity.view) {
const type = field.type;
if (type === schema_1.Model.RelationType.ManyHasMany ||
type === schema_1.Model.RelationType.OneHasMany ||
(type === schema_1.Model.RelationType.OneHasOne && !('joiningColumn' in field))) {
errors.add('This relation type is not allowed on a view entity. Only one-has-one owning and many-has one are allowed.');
}
}
if (model_1.isInverseRelation(field)) {

@@ -276,2 +302,7 @@ // todo

const inversedBy = field.inversedBy; // todo
if (targetEntity.view) {
if ('joiningColumn' in field) {
errors.add(`View entity ${targetEntity.name} cannot be referenced from an owning relation. Try switching the owning side.`);
}
}
if (inversedBy) {

@@ -333,2 +364,3 @@ const targetField = targetEntity.fields[inversedBy];

const tableNames = {};
const aliasedTypes = new Map();
for (const entity of entities) {

@@ -360,3 +392,13 @@ const description = `entity ${entity.name}`;

},
visitColumn: () => { },
visitColumn: (entity, column) => {
if (!column.typeAlias) {
return;
}
if (aliasedTypes.has(column.typeAlias) && aliasedTypes.get(column.typeAlias) !== column.type) {
errorBuilder
.for(column.name)
.add(`Type alias ${column.typeAlias} already exists for base type ${column.type}`);
}
aliasedTypes.set(column.typeAlias, column.type);
},
visitManyHasManyInverse: () => { },

@@ -363,0 +405,0 @@ visitOneHasMany: () => { },

{
"name": "@contember/schema-utils",
"version": "0.12.0-alpha.2",
"version": "0.12.0-alpha.4",
"license": "Apache-2.0",

@@ -11,7 +11,7 @@ "main": "dist/src/index.js",

"dependencies": {
"@contember/schema": "^0.12.0-alpha.2"
"@contember/schema": "^0.12.0-alpha.4"
},
"devDependencies": {
"@types/node": "^14.6.4"
"@types/node": "^15.12.5"
}
}

@@ -251,2 +251,4 @@ import { assertNever, isIt } from '../utils'

export const isColumn = (field: Model.AnyField): field is Model.AnyColumn => isIt<Model.AnyColumn>(field, 'columnType')
export const emptyModelSchema: Model.Schema = { entities: {}, enums: {} }

@@ -1,28 +0,31 @@

import { ProjectRole, Schema } from '@contember/schema'
import { Acl, ProjectRole, Schema } from '@contember/schema'
import { AllowAllPermissionFactory } from './acl'
export const normalizeSchema = <S extends Schema>(schema: S): S => {
if (!schema.acl.roles[ProjectRole.ADMIN]) {
schema = {
...schema,
acl: {
...schema.acl,
roles: {
...schema.acl.roles,
[ProjectRole.ADMIN]: {
stages: '*',
variables: {},
entities: new AllowAllPermissionFactory().create(schema.model),
s3: {
'**': {
upload: true,
read: true,
},
return {
...schema,
acl: {
...schema.acl,
roles: {
...schema.acl.roles,
[ProjectRole.ADMIN]: {
stages: '*',
variables: {},
entities: new AllowAllPermissionFactory().create(schema.model),
s3: {
'**': {
upload: true,
read: true,
},
},
...((schema.acl.roles?.[ProjectRole.ADMIN] as Acl.RolePermissions | undefined) || {}),
},
[ProjectRole.MIGRATION]: {
stages: '*',
entities: {},
variables: {},
},
},
}
},
}
return schema
}

@@ -39,3 +39,3 @@ import { Acl, Model } from '@contember/schema'

// }
const rolePermissions = this.validateRolePermissions(roles[role], validRoles, errorBuilder.for(role))
const rolePermissions = this.validateRolePermissions(roles[role], Object.keys(roles), errorBuilder.for(role))
if (rolePermissions !== undefined) {

@@ -50,3 +50,3 @@ validRoles[role] = rolePermissions

permissions: unknown,
roles: Acl.Schema['roles'],
roles: string[],
errorBuilder: ErrorBuilder,

@@ -85,7 +85,3 @@ ): Acl.RolePermissions | undefined {

private validateInherits(
inherits: unknown,
roles: Acl.Schema['roles'],
errorBuilder: ErrorBuilder,
): string[] | undefined {
private validateInherits(inherits: unknown, roles: string[], errorBuilder: ErrorBuilder): string[] | undefined {
if (inherits === undefined) {

@@ -100,6 +96,5 @@ return undefined

for (const inheritsFrom of inherits) {
if (!roles[inheritsFrom]) {
errorBuilder
.for(inheritsFrom)
.add('Referenced role not exists. Make sure you are defining roles in a right order')
if (!roles.includes(inheritsFrom)) {
// todo: check recursion
errorBuilder.for(inheritsFrom).add('Referenced role not exists.')
} else {

@@ -106,0 +101,0 @@ validRoles.push(inheritsFrom)

@@ -101,3 +101,3 @@ import { Model } from '@contember/schema'

if (typeof entity.tableName !== 'string') {
errors.for('tableName').add('Entity name must be a string')
errors.for('tableName').add('Table name must be a string')
return undefined

@@ -110,7 +110,28 @@ }

}
const partialEntity: Model.Entity = {
name: entity.name,
primary: entity.primary,
primaryColumn: entity.primaryColumn,
tableName: entity.tableName,
fields: {},
unique: {},
}
if (entity.view) {
const viewTmp = entity.view
if (!isObject(viewTmp)) {
errors.for('view').add('View must be an object')
return undefined
}
if (typeof viewTmp.sql !== 'string') {
errors.for('view', 'sql').add('View SQL must be a string')
return undefined
}
partialEntity.view = entity.view as Model.View
}
const validFields: Model.Entity['fields'] = {}
for (const [fieldName, field] of Object.entries(fields)) {
const fieldErrors = errors.for(fieldName)
const validField = this.validateField(entity.name, field, fieldErrors)
const validField = this.validateField(partialEntity, field, fieldErrors)
if (!validField) {

@@ -138,6 +159,3 @@ continue

return {
name: entity.name,
primary: entity.primary,
primaryColumn: entity.primaryColumn,
tableName: entity.tableName,
...partialEntity,
fields: validFields,

@@ -190,3 +208,3 @@ unique: validUniqueConstraints,

private validateField(entityName: string, field: unknown, errors: ErrorBuilder): Model.AnyField | undefined {
private validateField(partialEntity: Model.Entity, field: unknown, errors: ErrorBuilder): Model.AnyField | undefined {
if (!isObject(field)) {

@@ -208,12 +226,13 @@ errors.add('Field must be an object')

if (isRelation(field as any)) {
return this.validateRelation(entityName, field, errors)
return this.validateRelation(partialEntity, field, errors)
}
return (field as unknown) as Model.AnyColumn
return field as unknown as Model.AnyColumn
}
private validateRelation(
entityName: string,
partialEntity: Model.Entity,
field: UnknownObject,
errors: ErrorBuilder,
): Model.AnyRelation | undefined {
const entityName = partialEntity.name
const targetEntityName = field.target as string // todo

@@ -247,3 +266,15 @@ const targetEntity = this.model.entities[targetEntityName] || undefined

}
if (isInverseRelation((field as any) as Model.Relation)) {
if (partialEntity.view) {
const type = (field as any as Model.Relation).type
if (
type === Model.RelationType.ManyHasMany ||
type === Model.RelationType.OneHasMany ||
(type === Model.RelationType.OneHasOne && !('joiningColumn' in field))
) {
errors.add(
'This relation type is not allowed on a view entity. Only one-has-one owning and many-has one are allowed.',
)
}
}
if (isInverseRelation(field as any as Model.Relation)) {
// todo

@@ -299,2 +330,9 @@ const ownedBy = field.ownedBy

const inversedBy = field.inversedBy as string // todo
if (targetEntity.view) {
if ('joiningColumn' in field) {
errors.add(
`View entity ${targetEntity.name} cannot be referenced from an owning relation. Try switching the owning side.`,
)
}
}
if (inversedBy) {

@@ -345,3 +383,3 @@ const targetField = targetEntity.fields[inversedBy]

}
return (field as any) as Model.AnyRelation // todo
return field as any as Model.AnyRelation // todo
}

@@ -363,2 +401,3 @@

const tableNames: Record<string, string> = {}
const aliasedTypes = new Map<string, Model.ColumnType>()
for (const entity of entities) {

@@ -396,3 +435,13 @@ const description = `entity ${entity.name}`

},
visitColumn: () => {},
visitColumn: (entity, column) => {
if (!column.typeAlias) {
return
}
if (aliasedTypes.has(column.typeAlias) && aliasedTypes.get(column.typeAlias) !== column.type) {
errorBuilder
.for(column.name)
.add(`Type alias ${column.typeAlias} already exists for base type ${column.type}`)
}
aliasedTypes.set(column.typeAlias, column.type)
},
visitManyHasManyInverse: () => {},

@@ -399,0 +448,0 @@ visitOneHasMany: () => {},

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

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc