UNPKG

shyft

Version:

Model driven GraphQL API framework

253 lines (252 loc) 13.5 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSchema = exports.Schema = void 0; var util_1 = require("../util"); var Entity_1 = require("../entity/Entity"); var Action_1 = require("../action/Action"); var DataTypeUser_1 = require("../datatype/DataTypeUser"); var StorageType_1 = require("../storage/StorageType"); var Permission_1 = require("../permission/Permission"); var ViewEntity_1 = require("../entity/ViewEntity"); var ShadowEntity_1 = require("../entity/ShadowEntity"); var Schema = /** @class */ (function () { function Schema(setup) { var _this = this; if (setup === void 0) { setup = { entities: null, defaultStorageType: null, actions: null, defaultActionPermissions: null, permissionsMap: null, }; } this._entityMap = {}; this._actionMap = {}; this._userEntity = null; this._entityMap = {}; this._actionMap = {}; this._isValidated = false; this._userEntity = null; var entities = setup.entities, defaultStorageType = setup.defaultStorageType, actions = setup.actions, permissionsMap = setup.permissionsMap, defaultActionPermissions = setup.defaultActionPermissions; if (defaultStorageType) { util_1.passOrThrow(StorageType_1.isStorageType(defaultStorageType), function () { return 'Provided default storage type is invalid'; }); } this.defaultStorageType = defaultStorageType; if (permissionsMap) { util_1.passOrThrow(util_1.isMap(permissionsMap), function () { return 'Provided permissionsMap is invalid'; }); var permissionsMapKeys = Object.keys(permissionsMap); permissionsMapKeys.map(function (key) { util_1.passOrThrow(['entities', 'actions'].includes(key), function () { return 'Unknown property used in permissionsMap (allowed: entities, actions)'; }); }); if (permissionsMap.entities) { util_1.passOrThrow(util_1.isMap(permissionsMap.entities), function () { return 'Provided permissionsMap.entities is invalid'; }); var entityNames = Object.keys(permissionsMap.entities); entityNames.map(function (entityName) { var entityPermissions = permissionsMap.entities[entityName]; if (entityPermissions) { util_1.passOrThrow(util_1.isMap(entityPermissions), function () { return "Provided permissionsMap for '" + entityName + "' is invalid"; }); if (entityPermissions.read) { util_1.passOrThrow(Permission_1.isPermission(entityPermissions.read) || Permission_1.isPermissionsArray(entityPermissions.read), function () { return "Invalid 'read' permission definition in permissionsMap for '" + entityName + "'"; }); } if (entityPermissions.find) { util_1.passOrThrow(Permission_1.isPermission(entityPermissions.find) || Permission_1.isPermissionsArray(entityPermissions.find), function () { return "Invalid 'find' permission definition in permissionsMap for '" + entityName + "'"; }); } if (entityPermissions.mutations) { util_1.passOrThrow(util_1.isMap(entityPermissions.mutations), function () { return "Definition of mutations in permissionsMap for '" + entityName + "' needs to be a map of mutations and permissions"; }); var mutationNames = Object.keys(entityPermissions.mutations); mutationNames.map(function (mutationName) { util_1.passOrThrow(Permission_1.isPermission(entityPermissions.mutations[mutationName]) || Permission_1.isPermissionsArray(entityPermissions.mutations[mutationName]), function () { return "Invalid mutation permission definition in permissionsMap for '" + entityName + "." + mutationName + "'"; }); }); } } }); } this.permissionsMap = permissionsMap; } if (defaultActionPermissions) { util_1.passOrThrow(Permission_1.isPermission(defaultActionPermissions) || Permission_1.isPermissionsArray(defaultActionPermissions), function () { return 'Invalid permission definition for defaultActionPermissions'; }); this.defaultActionPermissions = defaultActionPermissions; } if (entities) { util_1.passOrThrow(util_1.isArray(entities, true), function () { return "Schema needs 'entities' to be an array of type Entity"; }); entities.map(function (entity) { return _this.addEntity(entity); }); } if (actions) { util_1.passOrThrow(util_1.isArray(actions), function () { return "Schema needs 'actions' to be an array of type Action"; }); actions.map(function (action) { return _this.addAction(action); }); } } Schema.prototype.addEntity = function (entity) { var _this = this; util_1.passOrThrow(Entity_1.isEntity(entity) || ViewEntity_1.isViewEntity(entity) || ShadowEntity_1.isShadowEntity(entity), function () { return 'Provided object to schema is not an entity or view entity or shadow entity'; }); util_1.passOrThrow(!this._entityMap[entity.name], function () { return "Entity '" + entity.name + "' already registered with this schema"; }); if (entity.isUserEntity) { util_1.passOrThrow(!this._userEntity, function () { return "Entity '" + entity.name + "' cannot be set as user entity, " + ("'" + _this._userEntity.name + "' is already the user entity"); }); this._userEntity = entity; } if (this.defaultStorageType) { entity._injectStorageTypeBySchema(this.defaultStorageType); } if (this.permissionsMap && this.permissionsMap.entities) { var entityDefaultPermissions = this.permissionsMap.entities[entity.name] || {}; entityDefaultPermissions.mutations = entityDefaultPermissions.mutations || {}; entityDefaultPermissions.subscriptions = entityDefaultPermissions.subscriptions || {}; var defaultPermissions = this.permissionsMap.entities._defaultPermissions; defaultPermissions.mutations = defaultPermissions.mutations || {}; defaultPermissions.subscriptions = defaultPermissions.subscriptions || {}; var newDefaultPermissions = { read: entityDefaultPermissions.read || defaultPermissions.read, find: entityDefaultPermissions.find || defaultPermissions.find, mutations: __assign(__assign({}, defaultPermissions.mutations), entityDefaultPermissions.mutations), subscriptions: __assign(__assign({}, defaultPermissions.subscriptions), entityDefaultPermissions.subscriptions), }; if (Entity_1.isEntity(entity) || ViewEntity_1.isViewEntity(entity)) { entity._injectDefaultPermissionsBySchema(newDefaultPermissions); } } entity._isRegistered = true; this._entityMap[entity.name] = entity; this._isValidated = false; }; Schema.prototype.getUserEntity = function (throwIfMissing) { util_1.passOrThrow(!throwIfMissing || this._userEntity, function () { return 'There is no user entity registered yet'; }); return this._userEntity; }; Schema.prototype._lazyLoadMissingEntities = function () { var _this = this; var foundMissingCount = 0; var entityNames = Object.keys(this._entityMap); entityNames.forEach(function (entityName) { var entity = _this._entityMap[entityName]; var attributes = entity.getAttributes(); var attributeNames = Object.keys(attributes); attributeNames.forEach(function (attributeName) { var attribute = attributes[attributeName]; if (Entity_1.isEntity(attribute.type)) { // const attributeTypeAsEntity = attribute.type as Entity var targetEntity_1 = attribute.type; if (_this._entityMap[targetEntity_1.name]) { util_1.passOrThrow(targetEntity_1._isRegistered, function () { return "Referenced entity '" + targetEntity_1.name + "' already registered with this schema"; }); } else { _this.addEntity(targetEntity_1); foundMissingCount++; } } }); }); if (foundMissingCount > 0) { this._lazyLoadMissingEntities(); } }; Schema.prototype.validate = function () { var _this = this; if (this._isValidated) { return; } util_1.passOrThrow(util_1.isMap(this._entityMap, true), function () { return 'Schema has no entities'; }); this._lazyLoadMissingEntities(); var entityNames = Object.keys(this._entityMap); if (this.permissionsMap && this.permissionsMap.entities) { var permissionsMapEntityNames = Object.keys(this.permissionsMap.entities); permissionsMapEntityNames.map(function (permissionsMapEntityName) { util_1.passOrThrow(entityNames.includes(permissionsMapEntityName) || permissionsMapEntityName === '_defaultPermissions', function () { return "permissionsMap includes permissions for unknown entity " + permissionsMapEntityName; }); }); } entityNames.forEach(function (entityName) { var entity = _this._entityMap[entityName]; var attributes = entity.getAttributes(); var attributeNames = Object.keys(attributes); // trigger validation and generation of permissions and indexes if (Entity_1.isEntity(entity) || ViewEntity_1.isViewEntity(entity)) { entity.getPermissions(); } if (Entity_1.isEntity(entity)) { var entityAsEntity = entity; entityAsEntity.getIndexes(); } attributeNames.forEach(function (attributeName) { var attribute = attributes[attributeName]; if (Entity_1.isEntity(attribute.type)) { var targetEntity_2 = attribute.type; util_1.passOrThrow(_this._entityMap[targetEntity_2.name], function () { return "Entity '" + targetEntity_2.name + "' (referenced by '" + entity.name + "') " + 'needs to be registered with this schema'; }); // keep track of references targetEntity_2.referencedBy(entity.name, attributeName); } else if (DataTypeUser_1.isDataTypeUser(attribute.type)) { // replace with actual user entity attribute.type = _this.getUserEntity(true); } }); }); var actionNames = Object.keys(this._actionMap); actionNames.forEach(function (actionName) { var action = _this._actionMap[actionName]; // trigger validation and generation of permissions action.getPermissions(); }); this._isValidated = true; }; Schema.prototype.getEntities = function () { this.validate(); return this._entityMap; }; Schema.prototype.addAction = function (action) { util_1.passOrThrow(Action_1.isAction(action), function () { return 'Provided object to schema is not an action'; }); util_1.passOrThrow(!this._actionMap[action.name], function () { return "Action '" + action.name + "' already registered with this schema"; }); if (this.defaultActionPermissions) { action._injectDefaultPermissionsBySchema(this.defaultActionPermissions); } this._actionMap[action.name] = action; this._isValidated = false; }; Schema.prototype.getActions = function () { this.validate(); return this._actionMap; }; return Schema; }()); exports.Schema = Schema; var isSchema = function (obj) { return obj instanceof Schema; }; exports.isSchema = isSchema;