UNPKG

type-arango

Version:

ArangoDB Foxx decorators and utilities for TypeScript

385 lines 19.2 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); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Collection = exports.getCollectionForContainer = exports.findCollectionForContainer = void 0; var joi_1 = require("../joi"); var __1 = require(".."); var index_1 = require("./index"); var utils_1 = require("../utils"); var _1 = require("."); var METHODS_BODYLESS = ['get', 'delete']; /** * Creates a new Collection for a decorated class */ function createCollectionFromContainer(someClass) { var c = new Collection(someClass); __1.collections.push(c); return c; } /** * Finds a collection for a decorated class */ function findCollectionForContainer(someClass) { return __1.collections.find(function (c) { return someClass === c.Class || someClass.prototype instanceof c.Class; }); } exports.findCollectionForContainer = findCollectionForContainer; /** * Returns the respective collection instance for a decorated class */ function getCollectionForContainer(someClass) { var col = findCollectionForContainer(someClass); if (col) return col; return createCollectionFromContainer(someClass); } exports.getCollectionForContainer = getCollectionForContainer; /** * Collections represent tables in ArangoDB */ var Collection = /** @class */ (function () { /** * Creates a new collection instance */ function Collection(Class) { this.Class = Class; this.completed = false; this.schema = {}; this.routes = []; this.roles = { creators: [], readers: [], updaters: [], deleters: [] }; this.decorator = {}; this.name = Collection.toName(Class.name); this.db = __1.isActive ? utils_1.db._collection(this.name) : null; } /** * Returns a valid collection name */ Collection.toName = function (input) { return __1.config.prefixCollectionName ? module.context.collectionName(input) : input; }; Object.defineProperty(Collection.prototype, "allowUserKeys", { /** * Whether users can provide custom document keys on creation */ get: function () { var keyOptions = this.opt && this.opt.keyOptions; return !keyOptions ? false : (keyOptions && keyOptions.allowUserKeys === true && keyOptions.type !== 'autoincrement'); }, enumerable: false, configurable: true }); Object.defineProperty(Collection.prototype, "route", { get: function () { var name = this.name; name = name.charAt(0).toLowerCase() + name.substr(1); if (__1.config.dasherizeRoutes) name = name.replace(/[A-Z]/g, function (m) { return '-' + m.toLowerCase(); }); return name; }, enumerable: false, configurable: true }); Collection.prototype.addRoles = function (key, roles, onlyWhenEmpty) { if (onlyWhenEmpty === void 0) { onlyWhenEmpty = true; } if (onlyWhenEmpty && this.roles[key].length) return; this.roles[key] = utils_1.concatUnique(this.roles[key], roles); if (this.doc) this.doc.roles = utils_1.concatUnique(this.doc.roles, roles); // else console.log('CANNOT ADD ROLES, DOCUMENT NOT READY') }; Collection.prototype.decorate = function (decorator, data) { this.decorator[decorator] = __spreadArrays((this.decorator[decorator] || []), [__assign(__assign({}, data), { decorator: decorator })]); }; Object.defineProperty(Collection.prototype, "routeAuths", { get: function () { return (this.decorator['Route.auth'] || []).map(function (d) { return d.authorizeFn; }).reverse(); }, enumerable: false, configurable: true }); Object.defineProperty(Collection.prototype, "routeRoles", { get: function () { return (this.decorator['Route.roles'] || []).map(function (d) { return d.rolesFn; }).reverse(); }, enumerable: false, configurable: true }); Collection.prototype.query = function (q) { if (typeof q === 'string') { return utils_1.db._query(q); } if (!q.keep) { q.unset = []; if (__1.config.stripDocumentId) q.unset.push('_id'); if (__1.config.stripDocumentRev) q.unset.push('_rev'); if (__1.config.stripDocumentKey) q.unset.push('_key'); } return utils_1.db._query(utils_1.queryBuilder(this.name, q)); }; Collection.prototype.finalize = function () { var _a = this.decorator, Collection = _a.Collection, Route = _a.Route, Task = _a.Task, Function = _a.Function; var _b = Collection[0], ofDocument = _b.ofDocument, _c = _b.options, options = _c === void 0 ? {} : _c; this.opt = options; if (options.name) { this.name = options.name; } var doc = this.doc = index_1.getDocumentForContainer(utils_1.argumentResolve(ofDocument)); doc.col = this; if (options.creators) this.addRoles('creators', options.creators, false); if (options.readers) this.addRoles('readers', options.readers, false); if (options.updaters) this.addRoles('updaters', options.updaters, false); if (options.deleters) this.addRoles('deleters', options.deleters, false); if (__1.isActive) { // create collection if (!this.db) { __1.logger.info('Creating ArangoDB Collection "%s"', this.name); var of = options.of, creators = options.creators, readers = options.readers, updaters = options.updaters, deleters = options.deleters, roles = options.roles, auth = options.auth, routes = options.routes, opt = __rest(options, ["of", "creators", "readers", "updaters", "deleters", "roles", "auth", "routes"]); this.db = doc.isEdge ? utils_1.db._createEdgeCollection(this.name, opt || {}) : utils_1.db._createDocumentCollection(this.name, opt || {}); } // create indices for (var _i = 0, _d = doc.indexes; _i < _d.length; _i++) { var options_1 = _d[_i].options; this.db.ensureIndex(options_1); } var task = require('@arangodb/tasks'); var tasks = task.get(); // setup Tasks if (Task) { var _loop_1 = function (prototype, attribute, period, offset, id, name_1, params) { var opt = { id: id, offset: offset, name: name_1, params: params }; eval('opt.command = function ' + prototype[attribute].toString()); if (period > 0) opt.period = period; if (tasks.find(function (t) { return t.id === id; })) { __1.logger.debug('Unregister previously active task', id); task.unregister(id); } __1.logger.debug('Register task', opt); try { task.register(opt); } catch (e) { __1.logger.error('Could not register task:', e.message); } }; for (var _e = 0, Task_1 = Task; _e < Task_1.length; _e++) { var _f = Task_1[_e], prototype = _f.prototype, attribute = _f.attribute, period = _f.period, offset = _f.offset, id = _f.id, name_1 = _f.name, params = _f.params; _loop_1(prototype, attribute, period, offset, id, name_1, params); } } var aqlfunction = require('@arangodb/aql/functions'); // unregister old if (__1.config.unregisterAQLFunctionEntityGroup) { __1.logger.debug('Unregister AQLFunction-group "' + this.name + '::*"'); aqlfunction.unregisterGroup(this.name); } // setup AQLFunctions if (Function) for (var _g = 0, Function_1 = Function; _g < Function_1.length; _g++) { var _h = Function_1[_g], prototype = _h.prototype, attribute = _h.attribute, name_2 = _h.name, isDeterministic = _h.isDeterministic; __1.logger.debug('Register AQLFunction "' + name_2 + '"'); var f = null; eval('f = function ' + prototype[attribute].toString()); aqlfunction.register(name_2, f, isDeterministic); } } if (Route) for (var _j = 0, Route_1 = Route; _j < Route_1.length; _j++) { var _k = Route_1[_j], prototype = _k.prototype, attribute = _k.attribute, method = _k.method, pathOrRolesOrOptions = _k.pathOrRolesOrOptions, schemaOrRolesOrSummary = _k.schemaOrRolesOrSummary, rolesOrSchemaOrSummary = _k.rolesOrSchemaOrSummary, summaryOrSchemaOrRoles = _k.summaryOrSchemaOrRoles, options_2 = _k.options; var schema = void 0; var a = utils_1.argumentResolve(pathOrRolesOrOptions, function (inp) { return utils_1.enjoi(inp, 'required'); }, joi_1.Joi); var opt = Object.assign({ queryParams: [] }, typeof a === 'string' ? { path: a } : Array.isArray(a) ? { roles: a } : typeof a === 'object' && a && !a.method ? { schema: a.isJoi ? a : utils_1.enjoi(a) } : a || {}); // allow options for schema param if (utils_1.isObject(schemaOrRolesOrSummary)) { opt = Object.assign(schemaOrRolesOrSummary, opt); } else { schema = utils_1.argumentResolve(schemaOrRolesOrSummary, function (inp) { return utils_1.enjoi(inp, 'required'); }, joi_1.Joi); if (schema instanceof Array) { opt.roles = schema; } else if (typeof schema === 'string') { opt.summary = schema; } else if (typeof schema === 'object' && schema) { } else schema = null; } // allow options for roles param if (utils_1.isObject(rolesOrSchemaOrSummary)) { opt = Object.assign(rolesOrSchemaOrSummary, opt); } else { var roles = utils_1.argumentResolve(rolesOrSchemaOrSummary, function (inp) { return utils_1.enjoi(inp, 'required'); }, joi_1.Joi); if (roles instanceof Array) { opt.roles = roles; } else if (typeof roles === 'string') { opt.summary = roles; } else if (typeof roles === 'object' && roles) { schema = roles; } } // allow options for summary param if (utils_1.isObject(summaryOrSchemaOrRoles)) { opt = Object.assign(summaryOrSchemaOrRoles, opt); } else { var summary = utils_1.argumentResolve(summaryOrSchemaOrRoles, function (inp) { return utils_1.enjoi(inp, 'required'); }, joi_1.Joi); if (summary instanceof Array) { opt.roles = summary; } else if (typeof summary === 'string') { opt.summary = summary; } else if (typeof summary === 'object' && summary) { schema = summary; } } if (options_2) opt = Object.assign(options_2, opt); if (!schema && opt.schema) { schema = utils_1.argumentResolve(opt.schema, function (inp) { return utils_1.enjoi(inp, 'required'); }, joi_1.Joi); } if (method === 'LIST') { method = 'get'; opt.action = 'list'; } else method = method.toLowerCase(); opt = index_1.Route.parsePath(opt, this.route); if (schema) { if (schema.isJoi) { } else { // support anonymous object syntax (joi => ({my:'object'})) schema = utils_1.enjoi(schema); } // treat schema as queryParam or pathParam if (schema._type === 'object') { // allow optional request body but default to required() schema = schema._flags.presence === 'optional' ? schema : schema.required(); // init params opt.pathParams = opt.pathParams || []; opt.queryParams = opt.queryParams || []; var i = 0; var _loop_2 = function (attr) { // attributes with a default value are optional if (attr.schema._flags.default) { attr.schema._flags.presence = 'optional'; } // check schema attr in pathParams if (opt.pathParams.find(function (p) { return p[0] === attr.key; })) { // override pathParam schema with route schema in order to specify more details opt.pathParams = opt.pathParams.map(function (p) { return p[0] === attr.key ? [p[0], attr.schema, p[2]] : p; }); // remove attr from schema schema._inner.children = schema._inner.children.filter(function (a) { return a.key !== attr.key; }); return "continue"; } else if (opt.queryParams.find(function (q) { return q[0] === attr.key; })) { // override queryParam schema with route schema in order to specify more details opt.queryParams = opt.queryParams.map(function (p) { return p[0] === attr.key ? [p[0], attr.schema, p[2]] : p; }); // remove attr from schema schema._inner.children = schema._inner.children.filter(function (a) { return a.key !== attr.key; }); } else { i++; } if (METHODS_BODYLESS.includes(method)) { var isRequired = attr.schema._flags.presence === 'required'; var operators = attr.schema._flags.operators; opt.queryParams.push([ attr.key, attr.schema, index_1.Scalar.iconRequired(isRequired) + ' ' + (attr.schema._description ? '**' + attr.schema._description + '**' : (isRequired ? '**Required' : '**Optional') + (" query parameter** " + (operators ? 'with operator' : '') + " \u2002`[ " + attr.key + ": " + (operators ? '[operator, value]' : attr.schema._type) + " ]`")) + (operators ? "\n \u3000\u2002`Operators: " + operators.join(', ') + "`" : '') + ("\n \u3000\u2002`Example: ?" + attr.key + "=" + (operators ? utils_1.arraySample(operators) + __1.config.paramOperatorSeparator : '') + (attr.schema._examples[0] || attr.schema._type) + "`") ]); } }; // loop schema keys for (var _l = 0, _m = schema._inner.children; _l < _m.length; _l++) { var attr = _m[_l]; _loop_2(attr); } if (!METHODS_BODYLESS.includes(method) && i) { opt.body = [schema]; } // if(i && !ROUTEmethod !== 'get' && method !== 'delete'){ // opt.body = [schema] // } } } // is MethodDecorator, replace callback with method if (attribute) { opt.handler = prototype[attribute]; opt.handlerName = attribute; } _1.getRouteForCollection(method, opt, this); } this.completed = true; // this.complete() __1.logger.info('Completed collection "%s"', this.name); }; return Collection; }()); exports.Collection = Collection; //# sourceMappingURL=Collection.model.js.map