{"version":3,"file":"js/208-17d4e88f608bc63cfaa3.js","mappings":"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","sources":["webpack://AppoPods/./app/javascript/nkp/models/core.js","webpack://AppoPods/./app/javascript/nkp/services/core/user_api_service.js","webpack://AppoPods/./app/javascript/nkp/utils/password.js","webpack://AppoPods/./app/javascript/nkp/utils/permissions.js","webpack://AppoPods/./vendor/javascript/fl/core/active_storage.js","webpack://AppoPods/./vendor/javascript/fl/core/api_services.js","webpack://AppoPods/./vendor/javascript/fl/core/model_factory.js","webpack://AppoPods/./vendor/javascript/fl/core/object_system.js"],"sourcesContent":["const _ = require('lodash');\nconst { has_permission } = require('../utils/permissions.js');\nconst { FlExtensions, FlClassManager } = require('fl/core/object_system');\nconst {\n FlModelBase, FlModelCache, FlModelFactory, FlGlobalModelFactory\n} = require('fl/core/model_factory');\nconst {\n ActiveStorageAttachment, ActiveStorageAttachedOne, ActiveStorageAttachedMany\n} = require('fl/core/active_storage');\n\n/**\n * @ngdoc module\n * @name nkp.models.core\n * @module nkp.models\n * @description This module contains the model services for core data classes.\n * These services are all registered with the {@sref FlGlobalModelFactory}.\n */\n\n/**\n * @ngdoc type\n * @name NkpCoreUser\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::User`\n */\n\nlet NkpCoreUser = FlClassManager.make_class({\n name: 'NkpCoreUser',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCoreUser#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUser#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a User object.\n\t * The method converts the following properties:\n\t *\n\t * - **avatar** into a {@sref ActiveStorageAttachedOne} object.\n\t * - **intro_json** into an object (from a JSON representation).\n\t * - **current_sign_in_at** into a Date.\n\t *\n\t * @param {Object} data An object containing a representation of the\n\t * user object. This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.avatar))\n\t {\n\t\t// Since ActiveStorageAttachedOne does not have an identifier, we can't cache it\n\n\t\tthis.avatar = new ActiveStorageAttachedOne(data.avatar);\n\t }\n\n\t if (!_.isUndefined(data.intro_json)) this.intro_json = this._convert_JSON_value(data.intro_json);\n\t if (!_.isUndefined(data.current_sign_in_at)) this.current_sign_in_at = new Date(data.current_sign_in_at);\n\n\t return true;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUser#has_role\n\t * @description\n\t * Check if the user has a given role.\n\t *\n\t * @param {String} role The name of the role to check; for example, `user` or `role-user`.\n\t *\n\t * @return {Boolean} Returns `true` if the user has role *role*, `false` otherwise.\n\t */\n\n\thas_role: function(role) {\n\t let r = role.toLowerCase();\n\t if (r.startsWith('role-')) r = r.substring(5);\n\n\t let t = _.find(this.roles, function(e, idx) {\n\t\treturn (e == r) ? true : false;\n\t });\n\n\t return (_.isString(t)) ? true : false;\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreUser#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the user object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::User'; }\n\t}\n },\n \n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUser#create\n\t * @classmethod\n\t * @description\n\t * Factory for a user object.\n\t *\n\t * @param {Object} data The representation of the user object.\n\t *\n\t * @return {NkpCoreUser} Returns an instance of {@sref NkpCoreUser}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCoreUser', data);\n\t}\n },\n\n extensions: [ ]\n});\n\n// we need to add documentation comments here\n\nNkpCoreUser.ROLE_USER = 'user';\nNkpCoreUser.ROLE_SYSADMIN = 'sysadmin';\nNkpCoreUser.ROLE_MODERATOR = 'moderator';\nNkpCoreUser.ROLE_ANONYMOUS = 'anonymous';\nNkpCoreUser.ROLE_UNMONITORED = 'unmonitored';\n\n/**\n * @ngdoc type\n * @name NkpCorePod\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::Pod`\n */\n\nlet NkpCorePod = FlClassManager.make_class({\n name: 'NkpCorePod',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCorePod#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCorePod#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a pod object.\n\t * The method converts the following properties:\n\t *\n\t * - **owner** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}).\n\t * - **members** into an array of {@sref NkpCorePodMember} objects.\n\t * - **avatar** into a {@sref ActiveStorageAttachedOne} object.\n\t * - **note_json** into an object (from a JSON representation).\n\t *\n\t * @param {Object} data An object containing a representation of the pod object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.owner))\n\t {\n\t\tthis.owner = FlModelFactory.defaultFactory().create(data.owner);\n\t }\n\n\t if (_.isArray(data.members))\n\t {\n\t\tthis.members = FlModelFactory.defaultFactory().create(data.members);\n\t }\n\n\t if (_.isObject(data.avatar))\n\t {\n\t\t// Since ActiveStorageAttachedOne does not have an identifier, we can't cache it\n\n\t\tthis.avatar = new ActiveStorageAttachedOne(data.avatar);\n\t }\n\n\t if (!_.isUndefined(data.note_json)) this.note_json = this._convert_JSON_value(data.note_json);\n\n\t // hack alert: in order to make the new_comment_count property reactive, we define it here\n\n\t if (_.isUndefined(this.new_comment_count)) this.new_comment_count = 0;\n\t \n\t return true;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name NkpCorePod#has_permission\n\t * @description\n\t * Check if a permission is in the pod's permission list.\n\t *\n\t * @param {String} p The permission name.\n\t *\n\t * @return {Boolean} Returns `true` if *p* is in the pod's permission list, `false` otherwise.\n\t */\n\n\thas_permission: function(p) {\n\t return has_permission(p, this.permissions);\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCorePod#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the pod object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::Pod'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCorePod#create\n\t * @classmethod\n\t * @description\n\t * Factory for a pod object.\n\t *\n\t * @param {Object} data The representation of the pod object.\n\t *\n\t * @return {NkpCorePod} Returns an instance of {@sref NkpCorePod}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCorePod', data);\n\t}\n },\n\n extensions: [ ]\n});\n\n/**\n * @ngdoc type\n * @name NkpCorePodMember\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::Pod::Member`\n */\n\nlet NkpCorePodMember = FlClassManager.make_class({\n name: 'NkpCorePodMember',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCorePodMember#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCorePodMember#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a conversation member object.\n\t * The method converts the following properties:\n\t *\n\t * - **actor** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}).\n\t * - **pod** into an instance of {@sref NkpCorePod}.\n\t * - The permission names in **permissions** are normalized to lowercase; also, a hash representation\n\t * of the permissions is converted to an array.\n\t *\n\t * @param {Object} data An object containing a representation of the topic object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.actor))\n\t {\n\t\tthis.actor = FlModelFactory.defaultFactory().create(data.actor);\n\t }\n\n\t if (_.isObject(data.pod))\n\t {\n\t\tthis.pod = FlModelFactory.defaultFactory().create(data.pod);\n\t }\n\n\t if (_.isArray(data.permissions)) {\n\t\tthis.permissions = _.map(data.permissions, function(p, idx) { return p.toLowerCase(); });\n\t } else if (_.isObject(data.permissions)) {\n\t\tthis.permissions = _.reduce(data.permissions, function(acc, pv, pk) {\n\t\t if (pv) acc.push(pk.toLowerCase());\n\t\t return acc;\n\t\t}, [ ]);\n\t }\n\n\t return true;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name NkpCorePodMember#has_permission\n\t * @description\n\t * Check if a permission is in the member's permission list.\n\t *\n\t * @param {String} p The permission name.\n\t *\n\t * @return {Boolean} Returns `true` if *p* is in the member's permission list, `false` otherwise.\n\t */\n\n\thas_permission: function(p) {\n\t return has_permission(p, this.permissions);\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCorePodMember#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the pod member object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::Pod::Member'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCorePodMember#create\n\t * @classmethod\n\t * @description\n\t * Factory for a topic object.\n\t *\n\t * @param {Object} data The representation of the topic object.\n\t *\n\t * @return {NkpCorePodMember} Returns an instance of {@sref NkpCorePodMember}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCorePodMember', data);\n\t}\n },\n\n extensions: [ ]\n});\n\n/**\n * @ngdoc type\n * @name NkpCoreResourcePod\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::ResourcePod`\n */\n\nlet NkpCoreResourcePod = FlClassManager.make_class({\n name: 'NkpCoreResourcePod',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCoreResourcePod#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreResourcePod#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a resource/pod object.\n\t * The method converts the following properties:\n\t *\n\t * - **container** into an instance of the appropriate container object (currently {@sref NkpCorePod)}.\n\t * - **resource** into an instance of the appropriate class.\n\t * - **resource_owner** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}).\n\t * - **resource_created_at** into a Date.\n\t * - **resource_updated_at** into a Date.\n\t *\n\t * @param {Object} data An object containing a representation of the resource/pod object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.container))\n\t {\n\t\tthis.pod = FlModelFactory.defaultFactory().create(data.container);\n\t }\n\n\t if (_.isObject(data.resource))\n\t {\n\t\tthis.resource = FlModelFactory.defaultFactory().create(data.resource);\n\t }\n\n\t if (_.isObject(data.resource_owner))\n\t {\n\t\tthis.resource_owner = FlModelFactory.defaultFactory().create(data.resource_owner);\n\t }\n\n\t if (!_.isUndefined(data.resource_created_at)) this.resource_created_at = new Date(data.resource_created_at);\n\t if (!_.isUndefined(data.resource_updated_at)) this.resource_updated_at = new Date(data.resource_updated_at);\n\n\t return true;\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreResourcePod#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the resource/pod object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::ResourcePod'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreResourcePod#create\n\t * @classmethod\n\t * @description\n\t * Factory for a resource/pod object.\n\t *\n\t * @param {Object} data The representation of the resource/pod object.\n\t *\n\t * @return {NkpCoreResourcePod} Returns an instance of {@sref NkpCorePod}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCoreResourcePod', data);\n\t}\n },\n\n extensions: [ ]\n});\n\n/**\n * @ngdoc type\n * @name NkpCoreActorState\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::ActorState`\n */\n\nlet NkpCoreActorState = FlClassManager.make_class({\n name: 'NkpCoreActorState',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCoreActorState#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreActorState#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a conversation member object.\n\t * The method converts the following properties:\n\t *\n\t * - **actor** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}).\n\t * - **recent_checked_at** into an instance of Date.\n\t *\n\t * @param {Object} data An object containing a representation of the tracking directive object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.actor))\n\t {\n\t\tthis.actor = FlModelFactory.defaultFactory().create(data.actor);\n\t }\n\n\t if (!_.isUndefined(data.recent_checked_at))\n\t {\n\t\tthis.recent_checked_at = new Date(data.recent_checked_at);\n\t }\n\n\t return true;\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreActorState#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the actor state object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::ActorState'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreActorState#create\n\t * @classmethod\n\t * @description\n\t * Factory for a topic object.\n\t *\n\t * @param {Object} data The representation of the topic object.\n\t *\n\t * @return {NkpCoreUser} Returns an instance of {@sref NkpCoreActorState}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCoreActorState', data);\n\t}\n },\n extensions: [ ]\n});\n\n/**\n * @ngdoc type\n * @name NkpCoreJoinInvitation\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::JoinInvitation`\n */\n\nlet NkpCoreJoinInvitation = FlClassManager.make_class({\n name: 'NkpCoreJoinInvitation',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCoreJoinInvitation#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreJoinInvitation#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a join invitation object.\n\t * The method converts the following properties:\n\t *\n\t * - **sent_by** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}).\n\t * - **pod** into an instance of {@sref NkpCorePod}.\n\t * - **accepted_by** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}).\n\t * - **emailed_at**, **state_at**, and **expires_at** are converted to `Date`.\n\t *\n\t * @param {Object} data An object containing a representation of the topic object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.sent_by))\n\t {\n\t\tthis.sent_by = FlModelFactory.defaultFactory().create(data.sent_by);\n\t }\n\n\t if (_.isObject(data.pod))\n\t {\n\t\tthis.pod = FlModelFactory.defaultFactory().create(data.pod);\n\t }\n\n\t if (_.isObject(data.accepted_by))\n\t {\n\t\tthis.accepted_by = FlModelFactory.defaultFactory().create(data.accepted_by);\n\t }\n\n\t if (!_.isNil(data.emailed_at)) this.emailed_at = new Date(data.emailed_at);\n\t if (!_.isNil(data.expires_at)) this.expires_at = new Date(data.expires_at);\n\t if (!_.isNil(data.state_at)) this.state_at = new Date(data.state_at);\n\n\t return true;\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreJoinInvitation#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the join invitation object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::JoinInvitation'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreJoinInvitation#create\n\t * @classmethod\n\t * @description\n\t * Factory for a topic object.\n\t *\n\t * @param {Object} data The representation of the topic object.\n\t *\n\t * @return {NkpCoreUser} Returns an instance of {@sref NkpCoreJoinInvitation}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCoreJoinInvitation', data);\n\t}\n },\n extensions: [ ]\n});\n\n/**\n * @ngdoc type\n * @name NkpCoreTrackingDirective\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::TrackingDirective`\n */\n\nlet NkpCoreTrackingDirective = FlClassManager.make_class({\n name: 'NkpCoreTrackingDirective',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCoreTrackingDirective#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreTrackingDirective#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a conversation member object.\n\t * The method converts the following properties:\n\t *\n\t * - **actor** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}).\n\t * - **target** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}\n\t * or {@sref NkpCorePod}).\n\t *\n\t * @param {Object} data An object containing a representation of the tracking directive object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.actor))\n\t {\n\t\tthis.actor = FlModelFactory.defaultFactory().create(data.actor);\n\t }\n\n\t if (_.isObject(data.target))\n\t {\n\t\tthis.target = FlModelFactory.defaultFactory().create(data.target);\n\t }\n\n\t return true;\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreTrackingDirective#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the tracking directive object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::TrackingDirective'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreTrackingDirective#create\n\t * @classmethod\n\t * @description\n\t * Factory for a topic object.\n\t *\n\t * @param {Object} data The representation of the topic object.\n\t *\n\t * @return {NkpCoreUser} Returns an instance of {@sref NkpCoreTrackingDirective}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCoreTrackingDirective', data);\n\t}\n },\n extensions: [ ]\n});\n\n/**\n * @ngdoc type\n * @name NkpCoreLinkedEntity\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::LinkedEntity`\n */\n\nlet NkpCoreLinkedEntity = FlClassManager.make_class({\n name: 'NkpCoreLinkedEntity',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCoreLinkedEntity#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreLinkedEntity#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a conversation member object.\n\t * The method converts the following properties:\n\t *\n\t * - **container** into an instance of the appropriate class.\n\t * - **owner** into an instance of the appropriate class (currently, a {@sref NkpCoreUser}).\n\t * - **attachment** (if non-null) into an instance of {@sref ActiveStorageAttachedOne} object.\n\t * - **master** (if non-null) into an instance of {@sref NkpCoreLinkedEntity} object.\n\t * - **regions** (if present) into an array of {@sref NkpCoreLinkedEntityRegion} objects.\n\t *\n\t * @param {Object} data An object containing a representation of the tracking directive object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.container))\n\t {\n\t\tthis.container = FlModelFactory.defaultFactory().create(data.container);\n\t }\n\n\t if (_.isObject(data.owner))\n\t {\n\t\tthis.owner = FlModelFactory.defaultFactory().create(data.owner);\n\t }\n\n\t if (_.isObject(data.master))\n\t {\n\t\tthis.master = FlModelFactory.defaultFactory().create(data.master);\n\t }\n\n\t if (_.isObject(data.attachment))\n\t {\n\t\tthis.attachment = FlModelFactory.defaultFactory().create(data.attachment);\n\t }\n\n\t if (_.isArray(data.regions)) {\n\t\tthis.regions = FlModelFactory.defaultFactory().create(data.regions);\n\t } else if (!_.isUndefined(data.regions)) {\n\t\tthis.regions = [ ];\n\t }\n\t \n\t return true;\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreLinkedEntity#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the linked entity object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::LinkedEntity'; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreLinkedEntity#LINK_TYPE_UPLOADED\n\t * @classproperty\n\t * @description The constant value for uploaded linked entities.\n\t *\n\t * @return {String} Returns the value of the **LINK_TYPE_UPLOADED** property in the object.\n\t */\n\n\tLINK_TYPE_UPLOADED: {\n\t get: function() { return 'uploaded'; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreLinkedEntity#LINK_TYPE_EXTERNAL\n\t * @classproperty\n\t * @description The constant value for external linked entities.\n\t *\n\t * @return {String} Returns the value of the **LINK_TYPE_EXTERNAL** property in the object.\n\t */\n\n\tLINK_TYPE_EXTERNAL: {\n\t get: function() { return 'external'; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreLinkedEntity#LINK_TYPE_REFERENCE\n\t * @classproperty\n\t * @description The constant value for reference linked entities.\n\t *\n\t * @return {String} Returns the value of the **LINK_TYPE_REFERENCE** property in the object.\n\t */\n\n\tLINK_TYPE_REFERENCE: {\n\t get: function() { return 'reference'; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreLinkedEntity#DATA_TYPE_IMAGE\n\t * @classproperty\n\t * @description The constant value for linked entities with image data type.\n\t *\n\t * @return {String} Returns the value of the **DATA_TYPE_IMAGE** property in the object.\n\t */\n\n\tDATA_TYPE_IMAGE: {\n\t get: function() { return 'image'; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreLinkedEntity#DATA_TYPE_LINK\n\t * @classproperty\n\t * @description The constant value for linked entities with link data type.\n\t *\n\t * @return {String} Returns the value of the **DATA_TYPE_LINK** property in the object.\n\t */\n\n\tDATA_TYPE_LINK: {\n\t get: function() { return 'link'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreLinkedEntity#create\n\t * @classmethod\n\t * @description\n\t * Factory for a topic object.\n\t *\n\t * @param {Object} data The representation of the topic object.\n\t *\n\t * @return {NkpCoreUser} Returns an instance of {@sref NkpCoreLinkedEntity}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCoreLinkedEntity', data);\n\t}\n },\n\n extensions: [ ]\n});\n \n/**\n * @ngdoc type\n * @name NkpCoreLinkedEntityRegion\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::LinkedEntity::Region`\n */\n\nlet NkpCoreLinkedEntityRegion = FlClassManager.make_class({\n name: 'NkpCoreLinkedEntityRegion',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCoreLinkedEntityRegion#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreLinkedEntityRegion#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a conversation member object.\n\t * The method converts the following properties:\n\t *\n\t * - **geometry** into an object from a JSON string representation.\n\t * - **linked_entity** into an instance of the associated linked entity.\n\t * - **author** into an instance of the associated author.\n\t *\n\t * @param {Object} data An object containing a representation of the region object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.linked_entity)) {\n\t\tthis.linked_entity = FlModelFactory.defaultFactory().create(data.linked_entity);\n\t }\n\n\t if (_.isObject(data.author)) {\n\t\tthis.author = FlModelFactory.defaultFactory().create(data.author);\n\t }\n\n\t if (_.isString(data.geometry)) {\n\t\tthis.geometry = JSON.parse(data.geometry);\n\t }\n\n\t return true;\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreLinkedEntityRegion#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the linked entity region object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::LinkedEntity::Region'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreLinkedEntityRegion#create\n\t * @classmethod\n\t * @description\n\t * Factory for a topic object.\n\t *\n\t * @param {Object} data The representation of the region object.\n\t *\n\t * @return {NkpCoreUser} Returns an instance of {@sref NkpCoreLinkedEntityRegion}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCoreLinkedEntityRegion', data);\n\t}\n },\n\n extensions: [ ]\n});\n\n// we need to add documentation comments here\n\nNkpCoreLinkedEntityRegion.MODE_CONTRIBUTOR = 'contributor';\nNkpCoreLinkedEntityRegion.MODE_FOLLOWER = 'follower';\nNkpCoreLinkedEntityRegion.MODE_BROADCAST = 'broadcast';\n\n/**\n * @ngdoc type\n * @name NkpCoreLinkedEntityShowcase\n * @module nkp.models.core\n * @requires FlModelBase\n * @description Model class for `Nkp::Core::LinkedEntity::Showcase`\n */\n\nlet NkpCoreLinkedEntityShowcase = FlClassManager.make_class({\n name: 'NkpCoreLinkedEntityShowcase',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name NkpCoreLinkedEntityShowcase#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreLinkedEntityShowcase#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a conversation member object.\n\t * The method converts the following properties:\n\t *\n\t * - **region** into an instance of the associated linked entity region.\n\t * - **annotation** into an instance of the associated annotation.\n\t *\n\t * @param {Object} data An object containing a representation of the showcase object.\n\t * This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isObject(data.region)) {\n\t\tthis.region = FlModelFactory.defaultFactory().create(data.region);\n\t }\n\n\t if (_.isObject(data.annotation)) {\n\t\tthis.annotation = FlModelFactory.defaultFactory().create(data.annotation);\n\t }\n\n\t return true;\n\t}\n },\n\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name NkpCoreLinkedEntityShowcase#TYPE_NAME\n\t * @classproperty\n\t * @description The class name of the linked entity showcase object.\n\t *\n\t * @return {String} Returns the (Ruby) class name of the object.\n\t */\n\n\tTYPE_NAME: {\n\t get: function() { return 'Nkp::Core::LinkedEntity::Showcase'; }\n\t}\n },\n\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreLinkedEntityShowcase#create\n\t * @classmethod\n\t * @description\n\t * Factory for a linked entity showcase object.\n\t *\n\t * @param {Object} data The representation of the showcase object.\n\t *\n\t * @return {NkpCoreUser} Returns an instance of {@sref NkpCoreLinkedEntityShowcase}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('NkpCoreLinkedEntityShowcase', data);\n\t}\n },\n\n extensions: [ ]\n});\n\nFlGlobalModelFactory.register('nkp.models.core', [\n { service: NkpCoreUser, class_name: 'Nkp::Core::User' },\n { service: NkpCorePod, class_name: 'Nkp::Core::Pod' },\n { service: NkpCorePodMember, class_name: 'Nkp::Core::Pod::Member' },\n { service: NkpCoreResourcePod, class_name: 'Nkp::Core::ResourcePod' },\n { service: NkpCoreActorState, class_name: 'Nkp::Core::ActorState' },\n { service: NkpCoreJoinInvitation, class_name: 'Nkp::Core::JoinInvitation' },\n { service: NkpCoreTrackingDirective, class_name: 'Nkp::Core::TrackingDirective' },\n { service: NkpCoreLinkedEntity, class_name: 'Nkp::Core::LinkedEntity' },\n { service: NkpCoreLinkedEntityRegion, class_name: 'Nkp::Core::LinkedEntity::Region' },\n { service: NkpCoreLinkedEntityShowcase, class_name: 'Nkp::Core::LinkedEntity::Showcase' }\n]);\n\nmodule.exports = {\n NkpCoreUser,\n NkpCorePod,\n NkpCorePodMember,\n NkpCoreResourcePod,\n NkpCoreActorState,\n NkpCoreJoinInvitation,\n NkpCoreTrackingDirective,\n NkpCoreLinkedEntity,\n NkpCoreLinkedEntityRegion,\n NkpCoreLinkedEntityShowcase\n};\n","const _ = require('lodash');\nconst { FlExtensions, FlClassManager } = require('fl/core/object_system');\nconst {\n FlModelBase, FlModelCache, FlModelFactory, FlGlobalModelFactory\n} = require('fl/core/model_factory');\nconst {\n FlAPIService, FlAPIServiceRegistry, FlGlobalAPIServiceRegistry\n} = require('fl/core/api_services');\n\n// This is imported so that webpack pulls in the sources, or we run the risk of not loading it\nconst { NkpCoreUser } = require('../../models/core');\n\nconst API_CFG = {\n root_url_template: '/nkp/core/users',\n namespace: 'nkp_core_user',\n data_names: [ 'user', 'users', 'pods', 'topic', 'topics' ]\n};\n\n/**\n * @ngdoc type\n * @name NkpCoreUserAPIService\n * @module nkp.services\n * @requires FlAPIService\n * @description API service class for communicating with the user API.\n * This API service manages interactions with the API for `Nkp::Core::User` objects.\n */\n\nlet NkpCoreUserAPIService = FlClassManager.make_class({\n name: 'NkpCoreUserAPIService',\n superclass: 'FlAPIService',\n /**\n * @ngdoc method\n * @name NkpCoreUserAPIService#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the following API configuration:\n * ```\n * {\n * root_url_template: '/nkp/core/users',\n * namespace: 'nkp_core_user',\n * data_names: [ 'user', 'users', 'pods', 'topic', 'topics' ]\n * }\n * ```\n * and passing *srv_cfg* as the second argument.\n * The `'pods'` entry in *data_names* is used by the `pods` action.\n * The `'topics'` entry in *data_names* is used by the `topics` action.\n *\n * @param {Object} srv_cfg Configuration for the service.\n */\n\n initializer: function(srv_cfg) {\n\tthis.__super_init('FlAPIService', API_CFG, srv_cfg);\n },\n\n instance_properties: {\n },\n\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUserAPIService#check_username\n\t * @description Make a :check_username call by calling `axios.get` against the\n\t * **check_username** URL.\n\t *\n\t * @param {String} username The username to check; this value is placed in the **username**\n\t * submission parameter.\n\t * @param {Object} [config] Configuration object to pass to `axios.get`; this object is\n\t * merged into the default HTTP configuration object.\n\t *\n\t * @return On success, returns a promise containing the response data.\n\t * Clients will register the error handler.\n\t */\n\n\tcheck_username: function(username, config) {\n\t let self = this;\n\t let cfg = this._make_config(config);\n\t cfg.params = { username: username };\n\n\t return this._http_service.get(this.url_path_for('check_username'), cfg)\n\t\t.then(function(r) {\n\t\t self._response = r;\n\t\t return r.data;\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUserAPIService#check_email\n\t * @description Make a :check_email call by calling `axios.get` against the\n\t * **check_email** URL.\n\t *\n\t * @param {String} email The email to check; this value is placed in the **email**\n\t * submission parameter.\n\t * @param {Object} [config] Configuration object to pass to `axios.get`; this object is\n\t * merged into the default HTTP configuration object.\n\t *\n\t * @return On success, returns a promise containing the response data.\n\t * Clients will register the error handler.\n\t */\n\n\tcheck_email: function(email, config) {\n\t let self = this;\n\t let cfg = this._make_config(config);\n\t cfg.params = { email: email };\n\n\t return this._http_service.get(this.url_path_for('check_email'), cfg)\n\t\t.then(function(r) {\n\t\t self._response = r;\n\t\t return r.data;\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUserAPIService#change_password\n\t * @description Make an :update_password call by calling `axios.patch` against the\n\t * **change_password** URL.\n\t *\n\t * @param {NkpCoreUser|Integer} user The user object, or identifier, for the user whose password\n\t * to change.\n\t * @param {String} current_password The current password.\n\t * @param {String} new_password The new password.\n\t * @param {String} confirm_password The new password, again; this value must match *new_password*.\n\t * @param {Object} [config] Configuration object to pass to `axios.patch`; this object is\n\t * merged into the default HTTP configuration object.\n\t *\n\t * @return On success, returns a promise containing the updated user.\n\t * Clients will register the error handler.\n\t */\n\n\tchange_password: function(user, current_password, new_password, confirm_password, config) {\n\t let self = this;\n\t let cfg = this._make_config(config);\n\t let params = {\n\t\tcurrent_password: current_password,\n\t\tpassword: new_password,\n\t\tpassword_confirmation: confirm_password\n\t };\n\n\t return this.patch(this.url_path_for('change_password', user),\n\t\t\t this._wrap_data({ wrapped: params }), cfg)\n\t\t.then(function(r) {\n\t\t self._response = r;\n\t\t return Promise.resolve(self._create_or_refresh_from_id(user, self.response_data(r)));\n\t\t})\n\t\t.catch(function(e) {\n\t\t return Promise.reject(e);\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUserAPIService#pods\n\t * @description Make a :pods call by calling `axios.get` against the **pods** URL.\n\t *\n\t * Note that this method has the same behavior as the `index` method; it just runs a query against\n\t * a different table, and returns results in the *pods* key. In particular, it uses the pagination\n\t * parameters, and therefore it should not be used if `index` calls are also made on the same service\n\t * object. (Separate service objects are OK.)\n\t *\n\t * @param {NkpCoreUser|Integer} user The user for which to get pods; can also be passed\n\t * as an integer object identifier.\n\t * @param {Object} [params] Parameters to pass in the request; the contents of this object are\n\t * merged into *config.params*, and eventually make their way to the query string.\n\t * @param {Object} [config] Configuration object to pass to `axios.get`; this object is\n\t * merged into the default HTTP configuration object.\n\t *\n\t * @return On success, returns a promise containing the response data.\n\t * Clients will register the error handler.\n\t */\n\n\tpods: function(user, params, config) {\n\t let self = this;\n\t let p = null;\n\t \n\t if (!_.isObject(params)) params = { };\n\t if ( _.isObject(params.to_hash))\n\t {\n\t\tp = params;\n\t }\n\t else\n\t {\n\t\tp = _.merge({ }, params, {\n\t\t to_hash: {\n\t\t\tto_hash: {\n\t\t\t pod: {\n\t\t\t\tverbosity: 'standard'\n\t\t\t }\n\t\t\t}\n\t\t }\n\t\t});\n\t }\n\t \n\t return this.get(this.url_path_for('pods', user), this._make_index_config(p, config))\n\t\t.then(function(r) {\n\t\t self._set_pagination_controls(r);\n\n\t\t // The response data contains an array of objects, and we need to modelize the :pod property\n\n\t\t let pods = _.map(self.response_data(r), function(p, idx) {\n\t\t\treturn {\n\t\t\t pod: self.modelFactory.create(p.pod),\n\t\t\t permissions: p.permissions\n\t\t\t};\n\t\t });\n\t\t return Promise.resolve(pods);\n\t\t})\n\t\t.catch(function(e) {\n\t\t return Promise.reject(self.response_error(e));\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUserAPIService#topics\n\t * @description Make a :topics call by calling `axios.get` against the **topics** URL.\n\t *\n\t * Note that this method has the same behavior as the `index` method; it just runs a query against\n\t * a different table, and returns results in the *topics* key. In particular, it uses the pagination\n\t * parameters, and therefore it should not be used if `index` calls are also made on the same service\n\t * object. (Separate service objects are OK.)\n\t *\n\t * @param {NkpCoreUser|Integer} user The user for which to get topics; can also be passed\n\t * as an integer object identifier.\n\t * @param {Object} [params] Parameters to pass in the request; the contents of this object are\n\t * merged into *config.params*, and eventually make their way to the query string.\n\t * @param {Object} [config] Configuration object to pass to `axios.get`; this object is\n\t * merged into the default HTTP configuration object.\n\t *\n\t * @return On success, returns a promise containing the response data.\n\t * Clients will register the error handler.\n\t */\n\n\ttopics: function(user, params, config) {\n\t let self = this;\n\t let p = null;\n\t \n\t if (!_.isObject(params)) params = { };\n\t if ( _.isObject(params.to_hash))\n\t {\n\t\tp = params;\n\t }\n\t else\n\t {\n\t\tp = _.merge({ }, params, {\n\t\t /*\n\t\t to_hash: {\n\t\t\tto_hash: {\n\t\t\t topic: { verbosity: 'standard' },\n\t\t\t actor: { verbosity: 'id' }\n\t\t\t}\n\t\t }\n\t\t */\n\t\t});\n\t }\n\t \n\t return this.get(this.url_path_for('topics', user), this._make_index_config(p, config))\n\t\t.then(function(r) {\n\t\t self._set_pagination_controls(r);\n\t\t return Promise.resolve(self.modelFactory.create(self.response_data(r)));\n\t\t})\n\t\t.catch(function(e) {\n\t\t return Promise.reject(self.response_error(e));\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name NkpCoreUserAPIService#url_path_for\n\t * @description Overrides the base implementation to add support for the `check_username`, `check_email`,\n\t * `current`, `change_password`, `pods`, and `topics` actions.\n\t * It forwards to the superclass for the standard Rails actions `index`, `create`, `show`,\n\t * `update`, and `destroy`.\n\t *\n\t * @param {String} action The name of the action.\n\t * @param {Object|Integer} [target] Some actions need a target object whose identifier to place\n\t * in the path. The value is either an object that contains a **id** property, or the\n\t * identifier itself.\n\t *\n\t * @return {String|null} Returns the URL path for the action; if *action* is not supported,\n\t * returns `null`.\n\t */\n\n\turl_path_for: function(action, target) {\n\t let root_path = this._expand_url_template(this.root_url_template);\n\n\t if ((action == 'check_username') || (action == 'check_email') || (action == 'current'))\n\t {\n\t\treturn `${root_path}/${action}.json`;\n\t }\n\t else if ((action == 'change_password') || (action == 'pods') || (action == 'topics'))\n\t {\n\t\tlet tid = (_.isUndefined(target)) ? undefined : this._id(target);\n\t\treturn `${root_path}/${tid}/${action}.json`;\n\t }\n\t else\n\t {\n\t\treturn this.__super('FlAPIService', 'url_path_for', action, target);\n\t }\n\t}\n },\n\n class_methods: {\n },\n\n extensions: [ ]\n});\n\nFlGlobalAPIServiceRegistry.register('nkp.services', { NkpCoreUserAPIService: 'Nkp::Core::User' });\n\nmodule.exports = { NkpCoreUserAPIService };\n","const _ = require('lodash');\n\n/**\n * @ngdoc module\n * @name password\n * @module nkp.utils\n * @description\n * The functions generated by this module implement password-related functionality.\n */\n\nconst REASONS = {\n too_short: 'too_short',\n too_long: 'too_long',\n no_lowercase: 'no_lowercase',\n no_uppercase: 'no_uppercase',\n no_digit: 'no_digit',\n no_symbol: 'no_symbol'\n};\n\n/**\n * @ngdoc function\n * @name is_password_valid\n * @module nkp.utils.password\n * @description Checks if *password* is an acceptable password in NKP.\n * The password must meet the following criteria:\n *\n * - Password length must be at least *opts.min* long.\n * - Password length must be at most *opts.max* long.\n * - Must contain at least one lowercase letter.\n * - Must contain at least one uppercase letter.\n * - Must contain at least one digit.\n * - Must contain at least one symbol.\n *\n * The function returns an object containing two properties:\n *\n * - **is_valid* * is `true` if the password is valid, `false` otherwise.\n * - **reasons** is an array containing the list of reasons why it is not valid (it is empty if the password\n * is valid). The elements are strings of reason \"identifiers\": **too_short** and **too_long** indicate that\n * the password is too short or too long, respectively; **no_lowercase**, **no_uppercase**, **no_digit**,\n * and **no_symbol** that it is missing a lowercase, uppercase, numeric, or symbol character, respectively.\n *\n * For example, the return value for `my.password` returns\n *\n * ```\n * {\n * is_valid: false,\n * reasons: [ 'no_uppercase', 'no_digit' ]\n * }\n * ```\n *\n * @param {String} password The password to check.\n * @param {Object} opts Options for the function.\n *\n * @property {Number} [opts.min] The minimum length for the password; defaults to 8.\n * @property {Number} [opts.max] The maximum length for the password; defaults to 128.\n *\n * @return {Object} Returns an object as described above.\n */\n\nfunction is_password_valid(password, opts) {\n let min = _.get(opts, 'min', 8);\n let max = _.get(opts, 'max', 128);\n let rv = {\n\treasons: [ ]\n };\n \n if (password.length < min) {\n\trv.reasons.push(REASONS.too_short);\n } else if (password.length > max) {\n\trv.reasons.push(REASONS.too_long);\n } else {\n\tlet lc_count = 0;\n\tlet uc_count = 0;\n\tlet d_count = 0;\n\tlet s_count = 0;\n\tlet plen = password.length;\n\tvar c;\n\t\n\tfor (var idx=0 ; idx < plen ; idx++) {\n\t c = password.charAt(idx);\n\t \n\t if ((c >= 'a') && (c <= 'z')) {\n\t\tlc_count += 1;\n\t } else if ((c >= 'A') && (c <= 'Z')) {\n\t\tuc_count += 1;\n\t } else if ((c >= '0') && (c <= '9')) {\n\t\td_count += 1;\n\t } else {\n\t\ts_count += 1;\n\t }\n\t}\n\n\tif (lc_count == 0) rv.reasons.push(REASONS.no_lowercase);\n\tif (uc_count == 0) rv.reasons.push(REASONS.no_uppercase);\n\tif (d_count == 0) rv.reasons.push(REASONS.no_digit);\n\tif (s_count == 0) rv.reasons.push(REASONS.no_symbol);\n }\n\n rv.is_valid = (rv.reasons.length == 0);\n return rv;\n};\n\nmodule.exports = { REASONS, is_password_valid };\n","const _ = require('lodash');\n\n/**\n * @ngdoc module\n * @name permissions\n * @module nkp.utils\n * @description\n * The functions generated by this module implement permission-related functionality.\n * Permissions are stored as either arrays of permission names, or objects whose properties are permission\n * names, and values `true` or `false` (a missing permission is equivalent to a `false` value).\n */\n\n// These are permissions that must be explicitly granted even to owners\n\nconst explicit_permissions = [\n 'assign_to_container'\n];\n\n/**\n * @ngdoc function\n * @name has_permission\n * @module nkp.utils.permissions\n * @description Checks if *permissions* grants permission *p*.\n * If *permissions* is an array, it must contain *p*; if it is an object, it must have a property named *p* whose\n * value is `true`.\n *\n * @param {String} p The name of the permission.\n * @param {Array,Object} permissions The permissions to check.\n *\n * @return {boolean} Returns `true` if *permissions* grants permission *p*, `false` otherwise.\n */\n\nfunction has_permission(p, permissions) {\n let lcp = p.toLowerCase();\n if (_.isArray(permissions)) {\n\t// owners have all implicit permissions\n\n\tif (_.includes(explicit_permissions, lcp)) {\n\t return _.includes(permissions, lcp);\n\t} else {\n\t return (_.includes(permissions, 'owner')) ? true : _.includes(permissions, lcp);\n\t}\n } else if (_.isObject(permissions)) {\n\t// owners have all implicit permissions\n\n\tif (_.includes(explicit_permissions, lcp)) {\n\t return ((permissions[lcp]) ? true : false);\n\t} else {\n\t return (permissions['owner']) ? true : ((permissions[lcp]) ? true : false);\n\t}\n } else {\n\treturn false;\n }\n};\n\n/**\n * @ngdoc function\n * @name grant_permission\n * @module nkp.utils.permissions\n * @description Grants permission *p* to *permissions*.\n * If *permissions* is an array, *p* is added to its value; if it is an object, the property named *p* is set to\n * `true`.\n *\n * @param {String,Array} p The name of a permission, or an array of permission names. If the value is an array, all\n * permissions listed are granted.\n * @param {Array,Object} permissions The permissions to modify.\n *\n * @return {Array,Object} Returns the modified array or object containing the new permissions.\n */\n\nfunction grant_permission(p, permissions) {\n let pl = _.map(((_.isArray(p)) ? p : [ p ]), function(e, idx) { return e.toLowerCase(); });\n \n if (_.isArray(permissions)) {\n\treturn _.union(permissions, pl);\n } else if (_.isObject(permissions)) {\n\tlet np = _.reduce(pl, function(acc, e, idx) {\n\t acc[e] = true;\n\t return acc;\n\t}, { });\n\treturn _.assign({ }, permissions, np);\n }\n};\n\n/**\n * @ngdoc function\n * @name revoke_permission\n * @module nkp.utils.permissions\n * @description Revokes permission *p* from *permissions*.\n * If *permissions* is an array, *p* is removed from its value; if it is an object, the property named *p* is set to\n * `false`.\n *\n * @param {String,Array} p The name of a permission, or an array of permission names. If the value is an array, all\n * permissions listed are revoked.\n * @param {Array,Object} permissions The permissions to modify.\n *\n * @return {Array,Object} Returns the modified array or object containing the new permissions.\n */\n\nfunction revoke_permission(p, permissions) {\n let pl = _.map(((_.isArray(p)) ? p : [ p ]), function(e, idx) { return e.toLowerCase(); });\n \n if (_.isArray(permissions)) {\n\treturn _.difference(permissions, pl);\n } else if (_.isObject(permissions)) {\n\tlet np = _.reduce(pl, function(acc, e, idx) {\n\t acc[e] = false;\n\t return acc;\n\t}, { });\n\treturn _.assign({ }, permissions, np);\n } else {\n\treturn permissions;\n }\n};\n\nmodule.exports = { explicit_permissions, has_permission, grant_permission, revoke_permission };\n","/**\n * @ngdoc module\n * @name fl.active_storage\n * @requires fl.model_factory\n * @description\n * Support for ActiveRecord models.\n */\n\nconst _ = require('lodash');\nconst { FlExtensions, FlClassManager } = require('./object_system');\nconst {\n FlModelBase, FlModelCache, FlModelFactory, FlGlobalModelFactory\n} = require('./model_factory');\n\n/**\n * @ngdoc type\n * @name ActiveStorageAttachment\n * @module fl.active_storage\n * @requires FlModelBase\n * @description Model class for `ActiveStorage::Attachment`\n * This model encapsulate an instance of an ActiveStorage attachment object.\n * In addition to a number of metadata properties, the object contains an array of *variants*,\n * representation of the original data that have been transformed. Typically, image attachments\n * contain a number of variants (usually for different image sizes), whereas nonimage ones\n * include just the `original` style, the original file itself.\n */\n\nlet ActiveStorageAttachment = FlClassManager.make_class({\n name: 'ActiveStorageAttachment',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name ActiveStorageAttachment#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n instance_properties: {\n },\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachment#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of an attachment object.\n\t * \n\t * @param {Object} data An object containing a representation of the \n\t * attachment object. This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (!_.isArray(this.variants)) this.variants = [ ];\n\n\t return true;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachment#variant\n\t * @description\n\t * Returns the variant descriptor for a given style.\n\t * \n\t * @param {String} style The name of the style to look up.\n\t *\n\t * @return {Object} Returns an object containing the description of the variant:\n\t *\n\t * - **style** is the style name (should be equal to *style*).\n\t * - **params** is an object of processing parameters that were used to generate the\n\t * variant. A useful parameter is **resize**, the target size for the variant.\n\t * - **url** The path component of the URL to the variant file.\n\t *\n\t * Returns `undefined` if *style* is not in the attachments.\n\t */\n\n\tvariant: function(style) {\n\t let ls = style.toLowerCase();\n\t \n\t return _.find(this.variants, function(v, idx) {\n\t\treturn v.style.toLowerCase() == ls;\n\t });\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachment#variant_url\n\t * @description\n\t * Returns the variant URL for a given style.\n\t * \n\t * @param {String} style The name of the style to look up.\n\t *\n\t * @return {String} Returns a string containing the path component of the variant URL,\n\t * `null` if *style* is not in the list of variants.\n\t */\n\n\tvariant_url: function(style) {\n\t let v = this.variant(style);\n\t \n\t return (_.isObject(v)) ? v.url : null;\n\t}\n },\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachment#create\n\t * @classmethod\n\t * @description\n\t * Factory for an attachment object.\n\t * \n\t * @param {Object} data The representation of the user object.\n\t * \n\t * @return {ActiveStorageAttachment} Returns an instance of {@sref ActiveStorageAttachment}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('ActiveStorageAttachment', data);\n\t}\n },\n extensions: [ ]\n});\n\n/**\n * @ngdoc type\n * @name ActiveStorageAttachedOne\n * @module fl.active_storage\n * @requires FlModelBase\n * @description Model class for `ActiveStorage::Attached::One`\n * This model encapsulate an instance of a `has_one_attached` relationship.\n */\n\nlet ActiveStorageAttachedOne = FlClassManager.make_class({\n name: 'ActiveStorageAttachedOne',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name ActiveStorageAttachedOne#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n instance_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name ActiveStorageAttachedOne#attachment\n\t * @description Accessor for the one attachment in the relationship.\n\t * This property returns the value of *this.attachments[0]*.\n\t *\n\t * @return {ActiveStorageAttachment} The attachment object.\n\t */\n\n\tattachment: {\n\t get: function() { return this.attachments[0]; },\n\t set: function(attachment) { }\n\t}\n },\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachedOne#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a ActiveStorageAttachedOne object.\n\t * The **attachments** property, if present, is converted to an array of\n\t * {@sref ActiveStorageAttachment} instances.\n\t * \n\t * @param {Object} data An object containing a representation of the \n\t * proxy object. This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isArray(data.attachments))\n\t {\n\t\t// Since attachments don't have an identifier, they cannot be cached, and we\n\t\t// create them directly.\n\t\t\n\t\tthis.attachments = _.map(data.attachments, function(a, idx) {\n\t\t return new ActiveStorageAttachment(a);\n\t\t});\n\t }\n\n\t return true;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachedOne#variant\n\t * @description\n\t * Returns the variant descriptor for a given style for the single attachment.\n\t * This is a convenience method that checks if the attachment is non-null, and if so calls\n\t * `variant` against it.\n\t * \n\t * @param {String} style The name of the style to look up.\n\t *\n\t * @return {Object} Returns an object containing the description of the variant:\n\t *\n\t * - **style** is the style name (should be equal to *style*).\n\t * - **params** is an object of processing parameters that were used to generate the\n\t * variant. A useful parameter is **resize**, the target size for the variant.\n\t * - **url** The path component of the URL to the variant file.\n\t *\n\t * Returns `undefined` if *style* is not in the attachments.\n\t */\n\n\tvariant: function(style) {\n\t if (_.isNil(this.attachment)) return undefined;\n\n\t return this.attachment.variant(style);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachedOne#variant_url\n\t * @description\n\t * Returns the variant URL for a given style for the single attachment.\n\t * This is a convenience method that checks if the attachment is non-null, and if so calls\n\t * `variant_url` against it.\n\t * \n\t * @param {String} style The name of the style to look up.\n\t *\n\t * @return {String} Returns a string containing the path component of the variant URL,\n\t * `null` if *style* is not in the list of variants.\n\t */\n\n\tvariant_url: function(style) {\n\t if (_.isNil(this.attachment)) return undefined;\n\n\t return this.attachment.variant_url(style);\n\t}\n },\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachedOne#create\n\t * @classmethod\n\t * @description\n\t * Factory for a `has_one_attached` relationship object.\n\t * \n\t * @param {Object} data The representation of the relationship object.\n\t * \n\t * @return {ActiveStorageAttachedOne} Returns an instance of {@sref ActiveStorageAttachedOne}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('ActiveStorageAttachedOne', data);\n\t}\n },\n extensions: [ ]\n});\n\n/**\n * @ngdoc type\n * @name ActiveStorageAttachedMany\n * @module fl.active_storage\n * @requires FlModelBase\n * @description Model class for `ActiveStorage::Attached::Many`\n * This model encapsulate an instance of a `has_many_attached` relationship.\n */\n\nlet ActiveStorageAttachedMany = FlClassManager.make_class({\n name: 'ActiveStorageAttachedMany',\n superclass: 'FlModelBase',\n /**\n * @ngdoc method\n * @name ActiveStorageAttachedMany#constructor\n * @description The constructor; called during `new` creation.\n * Calls the superclass implementation, passing the value of *data*.\n *\n * @param {Object} data Model data.\n */\n\n initializer: function(data) {\n\tthis.__super_init('FlModelBase', data);\n },\n instance_properties: {\n },\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachedMany#refresh\n\t * @description\n\t * Refresh the state of the instance based on the contents\n\t * of the hash representation of a ActiveStorageAttachedMany object.\n\t * The **attachments** property, if present, is converted to an array of\n\t * {@sref ActiveStorageAttachment} instances.\n\t * \n\t * @param {Object} data An object containing a representation of the \n\t * proxy object. This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t */\n\n\trefresh: function(data) {\n\t if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\n\t if (_.isArray(data.attachments))\n\t {\n\t\t// Since attachments don't have an identifier, they cannot be cached, and we\n\t\t// create them directly.\n\t\t\n\t\tthis.attachments = _.map(data.attachments, function(a, idx) {\n\t\t return new ActiveStorageAttachment(a);\n\t\t});\n\t }\n\n\t return true;\n\t}\n },\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name ActiveStorageAttachedMany#create\n\t * @classmethod\n\t * @description\n\t * Factory for a `has_many_attached` relationship object.\n\t * \n\t * @param {Object} data The representation of the relationship object.\n\t * \n\t * @return {ActiveStorageAttachedMany} Returns an instance of {@sref ActiveStorageAttachedMany}.\n\t */\n\n\tcreate: function(data) {\n\t return FlClassManager.modelize('ActiveStorageAttachedMany', data);\n\t}\n },\n extensions: [ ]\n});\n\nFlGlobalModelFactory.register('fl.active_storage', [\n { service: ActiveStorageAttachment, class_name: 'ActiveStorage::Attachment' },\n { service: ActiveStorageAttachedOne, class_name: 'ActiveStorage::Attached::One' },\n { service: ActiveStorageAttachedMany, class_name: 'ActiveStorage::Attached::Many' }\n]);\n\nmodule.exports = { ActiveStorageAttachment, ActiveStorageAttachedOne, ActiveStorageAttachedMany };\n","/**\n * @ngdoc module\n * @name fl.api_services\n * @requires fl.model_factory\n * @description\n * Floopstreet API service base functionality.\n * This module exports the following functionality:\n */\n\nconst _ = require('lodash');\nconst axios = require('axios');\nconst { FlExtensions, FlClassManager } = require('./object_system');\nconst {\n FlModelBase, FlModelCache, FlModelFactory, FlGlobalModelFactory\n} = require('./model_factory');\n\nconst DEFAULT_SRV_CFG = {\n xsrfCookieName: 'XSRF-TOKEN',\n xsrfHeaderName: 'X-XSRF-TOKEN',\n modelFactory: FlModelFactory.defaultFactory()\n};\n\n/**\n * @ngdoc type\n * @name FlAPIService\n * @module fl.api_services\n * @requires FlModelFactory\n * @description FlAPIService is the base class for API services.\n * This class implements the common functionality for communicating with a standard Rails resource\n * API: it defines methods to trigger the standard actions **index**, **show**, **create**, **update**, and\n * **destroy**. Clients then provide a configuration that customizes this generic implementation.\n *\n * There are two ways to use this service:\n * 1. Create an instance of FlAPIService with appropriate configuration.\n * 2. Define a subclass that encapsulates the configuration and optionally also adds API-specific\n * entry points.\n *\n * For example, say there is a server API at `/my/data` that manages instances\n * of `My::Datum`; this API is a standard CRUD RESTful API as generated by Rails.\n * The API returns data as a JSON object containing the keys `data` or `datum`\n * (the former when collections are returned as by the **index** action, the latter\n * when single items are returned). Sumbission parameters are encapsulated in the\n * `my_datum` key. You can create a service to communicate with this API like this:\n * ```\n * let srv = new FlAPIService({\n * root_url_template: '/my/data',\n * namespace: 'my_datum',\n * data_names: [ 'data', 'datum' ]\n * });\n * ```\n * Alternatively, you can define a subclass of FlAPIService:\n * ```\n * let MyAPIService = FlClassManager.make_class({\n * name: 'MyAPIService',\n * superclass: 'FlAPIService',\n * initializer: function(srv_cfg) {\n * this.__super_init('FlAPIService', {\n * root_url_template: '/my/data',\n * namespace: 'my_datum',\n * data_names: [ 'data', 'datum' ]\n * }, srv_cfg);\n * }\n * });\n *\n * let srv = new MyAPIService();\n * ```\n * The second approach lets you define additional methods that implement triggering of\n * custom APIs. It also makes it possible to register service classes with {@sref FlAPIServiceRegistry}.\n *\n * To get a list of data:\n * ```\n * let srv = new MyDatumAPIService();\n * srv.index()\n * .then(function(data) {\n * // do something with the returned data\n * })\n * .catch(function(e) {\n * // report error\n * });\n * ```\n * Or to update an item:\n * ```\n * let id = getItemId();\n * let srv = new MyDatumAPIService();\n * srv.update(id, { wrapped: { prop1: 'prop1 value' },\n * unwrapped: { to_hash: { verbosity: 'complete' } })\n * .then(function(data) {\n * // do something with the returned data\n * })\n * .catch(function(r) {\n * // report error\n * });\n * ```\n * Note that the submission data can be split into wrapped and unwrapped components; the service object\n * places the wrapped in the appropriate namespace, using the API configuration options.\n *\n * #### Two types of API methods\n *\n * The service class defines two types of API methods. The first group consists of wrappers around\n * the standard HTTP methods `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, and `HEAD`, which are named\n * **get**, **post**, **put**, **patch**, **delete**, and **head**, respectively.\n *\n * The second group implements a higher level API to standard Rails controller actions\n * `index`, `show`, `create`, `update`, and `destroy`, which are named\n * **index**, **show**, **create**, **update**, and **destroy**, respectively.\n * These methods call the appropriate lower level API described above; for example, **index** and\n * **show** call **get**.\n *\n * #### Automatic generation of data model instances\n *\n * FlAPIService assumes that the API returns data objects as JSON representations; for example, it\n * assumes that the response for the **index** action looks something like this:\n * ```\n * {\n * \"data\":[\n * {\"type\":\"My::Datum\",\"api_root\":\"/my/data\",\"url_path\":\"/my/data/1\",\"fingerprint\":\"My::Datum/1\",\"id\":1,\"created_at\":\"...\",\"updated_at\":\"..\",\"value1\":\"...\",\"value2\":\"...\"},\n * {\"type\":\"My::Datum\",\"api_root\":\"/my/data\",\"url_path\":\"/my/data/2\",\"fingerprint\":\"My::Datum/2\",\"id\":2,\"created_at\":\"...\",\"updated_at\":\"..\",\"value1\":\"...\",\"value2\":\"...\"}\n * ],\n * \"_pg\":{\"_c\":2,\"_s\":20,\"_p\":2}\n * }\n * ```\n * The **index** code uses {@sref FlModelFactory} to instantiate an array of model objects from the array\n * of JSON structures returned in the **data** property, and therefore a model class should have been\n * registered for the `My::Model` type. (If no such class has been registered, `null` is placed in\n * the array.)\n *\n * #### The API protocol\n *\n * This service assumes that the server implements a specific API behavior (as described in the documentation\n * for the Ruby server layer, and specifically the `Fl::Core::Concerns::Controller::ApiResponse` concern).\n *\n * For successful responses, the body of the response is a JSON object that contains at least the property\n * **_status**, whose value is an object that contains the optional **status**, **message**, and **details** properties.\n * The presence of **_status** in the response body indicates success.\n * In addition, the response body may contain a **payload** property, whose value is an object containing\n * data returned by the API; its contents are API-specific. For the standard Rails resource actions, the contents\n * of **payload** are as follows:\n * - For **index**, a property containing the array of returned object representations; the name of the\n * property is provided in the service configuration. Additionally, **payload** contains the pagination\n * state in the **_pg** property. For example:\n * ```\n * \"payload\": {\n * \"users\": [ { \"fingerprint\": \"User/1\" }, { \"fingerprint\": \"User/2\" } ],\n * \"_pg\": { \"_c\" : 2, \"_s\" : 20, \"_p\" : 2}\n * }\n * ```\n * - For **create** and **update**, it is a property containing a single object representation; the name of the\n * property is provided in the service configuration. For example:\n * ```\n * \"payload\": {\n * \"user\": { \"fingerprint\": \"User/1\" }\n * }\n * ```\n * - For **destroy**, it is either an empty object, or it is not present. \n *\n * For error responses, the body of the response is a JSON object that contains the property\n * **_error**, whose value is an object that contains the following properties.\n * The presence of **_error** in the response body indicates an error.\n * - **type** is a string containing a \"tag\" for the error, and is meant for use by client code to implement\n * error-specific behavior.\n * - **message** is a string containing an error message.\n * - **details** is an object containing aditional error info, if available.\n *\n * For example:\n * ```\n * {\n * \"_error\": {\n * \"type\": \"not_found\",\n * \"message\": \"user 1234 does not exist\"\n * }\n * }\n * ```\n *\n * ##### Host (base) URLs\n *\n * The **root_url_template** in the configuration (and **shallow_root_url_template**) are slightly\n * misnamed, as they contain just the path component of the complete URL.\n * This is as it should be, because the API signature should not include the server address (because\n * the same API could be running on different servers).\n *\n * In a browser environment, the current page's server address is used if one is not provided, but in\n * other environments (for example, React native) there is no notion of a \"current page\" or\n * \"currrent server address.\" In this latter case, the API user must specify an absolute URL; the\n * mechanism for doing so is to pass a **baseURL** option in the server configuration object argument\n * in the constructor or in the network call methods like {@sref FlAPIService#get} and\n * {@sref FlAPIService#index}.\n * For example, to create a service instance that communicates with the server\n * at `http://srv.example.com:80`, pass the **baseURL** argument in the constructor:\n * ```\n * function get_data_promise() {\n * let srv = new MyAPIService({ baseURL : 'http://srv.example.com:80' });\n *\n * return srv.index();\n * }\n * ```\n * Alternatively, you can customize the base URL for each function call:\n * ```\n * function get_data_promise(baseURL) {\n * let srv = new MyAPIService();\n *\n * return srv.index(null, { baseURL : baseURL })\n * };\n * ```\n * (This last examples is a bit contrived, but you get the idea.)\n * Either approach is acceptable, although placing the base URL in the constructor might be a bit\n * cleaner. On the other hand, if you have a long lived service object that needs to switch target\n * servers, the per-call customization is what you want.\n *\n * ##### The status object\n *\n * The status object as returned by a successful method call contains the following properties:\n * - If the response body contains a **_status** object:\n * - **status** is the value of the **status** property in **_status**, if present; otherwise, it is\n * the status code from the response (typically in the 200 range, but could be in the 300s).\n * - **message** is the value of the **message** property in **_status**, if present; otherwise, it\n * is the message associated with the HTTP status code.\n * - **details** is the value of the **details** property in **_status**, if present.\n * - Otherwise:\n * - **status** is the status code from the response (typically in the 200 range, but could be in the\n * 300s).\n * - **message** is the message associated with the HTTP status code.\n *\n * ##### The error object\n *\n * The error object as returned by a failed method call contains the following properties:\n * - If the response body contains a **_error** object:\n * - **type** is the value of the **type** property in **_error**, if present; otherwise, it is\n * the status code from the response (typically in the 400 and 500 range).\n * - **message** is the value of the **message** property in **_error**, if present; otherwise, it\n * is the message associated with the HTTP status code.\n * - **details** is the value of the **details** property in **_error**, if present.\n * - Otherwise:\n * - **type** is the status code from the response, which should be in the 400 or 500 range.\n * - **message** is the message associated with the HTTP status code.\n *\n * ##### The pagination info\n *\n * Pagination info is an object that tracks the current state of a multipage query.\n * It contains the following properties:\n * - **_s** How many results to return per page.\n * - **_p** The next page to fetch, starting at 1 for the first page.\n * - **_c** How many results were returned by the last query. Note that, if `_c < _s`, then\n * no more results are available.\n *\n * ##### URL templates\n *\n * The configuration property **root_url_template** is used to generate the root URL.\n * The value may contain replacement directives of the form `${expr}`, similar to the syntax\n * used for ES6 template literals; these directives are executed in the context of the service object\n * (`this`), and inserted in the template to generate the root URL.\n * For example, the template `/my/${parent.id}/dependents` will\n * generate a root URL `/my/1234/dependents`, where `1234` is the result of the expression\n * `parent.id` evaluated in the context of `this`. This implies that the service object using this\n * template has also set a property named **parent**, typically from an argument to the constructor.\n *\n * Templates with replacement directives are typically used with nested resource APIs. For example,\n * a list and list item API pair may define two service API objects, a regular one for lists, and a\n * nested one for list items (list contents).\n * The list API service may use a configuration and class descriptor like this:\n * ```\n * const LIST_API_CFG = {\n * root_url_template: '/lists',\n * namespace: 'list',\n * data_names: [ 'list', 'lists' ]\n * };\n *\n * const LIST_SERVICE_DESC = {\n * name: 'ListAPIService',\n * superclass: 'FlAPIService',\n * initializer: function(srv_cfg) {\n * this.__super_init('FlAPIService', LIST_API_CFG, srv_cfg);\n * }\n * };\n * ```\n * The nested list item API service is set up like this:\n * ```\n * const LIST_ITEM_API_CFG = {\n * root_url_template: '/lists/${list.id}/list_items',\n * shallow_root_url_template: '/list_items',\n * namespace: 'list_item',\n * data_names: [ 'list_item', 'list_items' ]\n * };\n *\n * const LIST_ITEM_SERVICE_DESC = {\n * name: 'ListItemAPIService',\n * superclass: 'FlNestedAPIService',\n * initializer: function(list, srv_cfg) {\n * this.__super_init('FlNestedAPIService', LIST_ITEM_API_CFG, srv_cfg);\n * this.list = list;\n * }\n * };\n * ```\n * Note how the root URL template contains the directive `${list.id}`, and how the constructor takes\n * the list object that provides the nesting resource; this list object is saved in the **this.list**\n * property. Individual list items are accessed via the `/list_items` URL; for example, the URL for the\n * `show` action for the list item with identifier 1234 in list `3456` is `/list_items/1234` rather\n * than `/lists/3456/list_items/1234`.\n *\n * ##### Rails nested resources\n *\n * The base service API class {@sref FlAPIService} can handle interactions with\n * {@sref Rails-nested-resources Rails nested resources} out of the box; however, we define a\n * specialized {@sref FlNestedAPIService} class that overrides the URL generation functionality to\n * support shallow routing as well as standard nested routing.\n *\n * #### Webpack\n *\n * API service code relies on registered data model classes to generate model instances of the\n * appropriate type. Unfortunately, {@sref Webpack} does not add a source file if its exports\n * are nowhere imported by the other files in the package. As a consequence, the data model class\n * associated with a given API service is not registered, and the data returned by **index** and\n * **show** is `null`. For example, the `MyAPIService` class listed above expects to retrieve\n * instances of the `My::Model` type, via the `MyModel` data model class:\n * ```\n * FlGlobalAPIServiceRegistry.register('my.services', { MyAPIService: 'My::Model' });\n * ```\n * If no other sources import `MyModel`, then a call to {@sref FlAPIService#show} attempts to\n * load the model class for `My::Model`, finds none, and returns `null`.\n *\n * Typically, the source file for a data model includes registration code like this:\n * ```\n * FlModelFactory.defaultFactory().register('my.models', [\n * { service: MyModel, class_name: 'My::Model' }\n * ]);\n * ```\n * To ensure that the source file is packed (and therefore the class is registered), add the\n * following statement in the source for `MyAPIService`:\n * ```\n * const { MyModel } = require('my/models/my_model');\n * ```\n * (or equivalent).\n */\n\nlet FlAPIService = FlClassManager.make_class({\n name: 'FlAPIService',\n /**\n * @ngdoc method\n * @name FlAPIService#constructor\n * @description The constructor; called during `new` creation.\n *\n * @param {Object} api_cfg Configuration for the API object.\n * @property {String} api_cfg.root_url_template The template used to generate the path component\n * of the URL.\n * The value may contain replacement directives of the form `${expr}`, similar to the syntax\n * used for ES6 template literals. For example, the template `/my/${parent.id}/dependents` will\n * generate a root URL `/my/1234/dependents`, where `1234` is the result of the expression\n * `parent.id` (looked up in **this**). Templates with replacement directives are\n * typically used with nested resource APIs.\n * @property {String} api_cfg.namespace The parameter namespace for create/update calls.\n * Parameters will be wrapped inside this namespace; for example, if the namespace is `ns`,\n * then the submission parameters `{ p1: 1, p2: 2 }` are actually sent to the server as\n * `{ ns: { p1: 1, p2: 2 } }`.\n * @property {Array} api_cfg.data_names An array of property names that contain\n * response data. These are typically the singular and plural version of the\n * object name. For the example above, use `[ 'datum', 'data' ]`; for an API that returns user\n * objects, use `[ 'user', 'users' ]`.\n * @property {Array} api_cfg.pg_names An array of property names that contain the\n * pagination controls. The service looks up each in the order in which they are listed\n * in the array, and loads the first match in the pagination controls.\n * The default value is the array `[ '_pg' ]`.\n * @param {Object} srv_cfg Configuration for the service. A few standard properties in the\n * object are described below; various services may include additional ones.\n * See the properties section for details.\n * @property {Object} srv_cfg.axios The underlying {@sref Axios} service to use for HTTP requests.\n * By default, an instance of Axios is created and installed, but one can provide a custom\n * instance if desired. This feature is often used for testing, to install a mocked version of Axios.\n * @property {Object} srv_cfg.modelFactory The instance of {@sref FlModelFactory} to use to create\n * model instances.\n * Defaults to {@sref FlGlobalModelFactory}.\n * @property {String} srv_cfg.xsrfCookieName The name of the cookie to use as a value for the XSRF token.\n * Defaults to `XSRF-TOKEN`.\n * @property {String} srv_cfg.xsrfHeaderName The name of the http header that carries the XSRF token\n * value.\n * Defaults to `X-XSRF-TOKEN`.\n * @property {String} srv_cfg.xsrfToken The value of the XSRF token.\n * Defaults to `undefined`.\n */\n initializer: function(api_cfg, srv_cfg) {\n\tthis._api_cfg = _.merge({ }, (_.isObject(api_cfg)) ? api_cfg : { });\n\tthis._srv_cfg = _.merge({ }, FlAPIService.getServiceConfig(), (_.isObject(srv_cfg)) ? srv_cfg : { });\n\n\tthis._http_service = (_.isNil(this._srv_cfg.axios)) ? axios : this._srv_cfg.axios;\n\tthis._pg_names = (_.isArray(this._api_cfg.pg_names)) ? this._api_cfg.pg_names : [ '_pg' ];\n\tif (_.isNil(this._srv_cfg.modelFactory)) this._srv_cfg.modelFactory = FlModelFactory.defaultFactory();\n\n\tthis._showDidSucceed = null;\n\tthis.pagination_controls = 'init';\n },\n instance_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#xsrfCookieName\n\t * @description Accessor for the name of the XSRF cookie, from the current configuation.\n\t * This property is just an accessor for the `xsrfCookieName` configuration property\n\t * from the *srv_cfg* argument to the constructor.\n\t *\n\t * @param {String} name The name of the cookie to use as a value for the XSRF token.\n\t *\n\t * @return {String} The getter returns the name of the XSRF cookie from the current configuation.\n\t */\n\n\txsrfCookieName: {\n\t get: function() { return this._srv_cfg.xsrfCookieName; },\n\t set: function(name) { this._srv_cfg.xsrfCookieName = name; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#xsrfHeaderName\n\t * @description Accessor for the name of http header that carries the XSRF token value,\n\t * from the current configuation.\n\t * This property is just an accessor for the `xsrfHeaderName` configuration property\n\t * from the *srv_cfg* argument to the constructor.\n\t *\n\t * @param {String} name The name of the http header that carries the XSRF token value.\n\t *\n\t * @return {String} The getter returns the name of the XSRF header from the current configuation.\n\t */\n\n\txsrfHeaderName: {\n\t get: function() { return this._srv_cfg.xsrfHeaderName; },\n\t set: function(name) { this._srv_cfg.xsrfHeaderName = name; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#xsrfToken\n\t * @description Accessor for the value of the local XSRF token.\n\t * This property is just an accessor for the `xsrfToken` configuration property\n\t * from the *srv_cfg* argument to the constructor.\n\t *\n\t * @param {String} token The new value of the token.\n\t *\n\t * @return {String} The getter returns the current value of the local XSRF token.\n\t */\n\n\txsrfToken: {\n\t get: function() { return this._srv_cfg.xsrfToken; },\n\t set: function(token) { this._srv_cfg.xsrfToken = token; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#modelFactory\n\t * @description Getter for **modelFactory** property.\n\t * This property is just an accessor for the `modelFactory` configuration property\n\t * from the *srv_cfg* argument to the constructor.\n\t *\n\t * @return {String} Returns the value of the **modelFactory** property in the object.\n\t */\n\n\tmodelFactory: {\n\t get: function() { return this._srv_cfg.modelFactory; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#root_url_template\n\t * @description Getter for **root_url_template** configuration property.\n\t * @return {String} Returns the value of the **root_url_template** property in the API config object.\n\t */\n\n\troot_url_template: {\n\t get: function() {\n\t\treturn this._api_cfg.root_url_template;\n\t }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#namespace\n\t * @description Getter for the **namespace** configuration property.\n\t * @return {String} Returns the value of the **namespace** property in the API config object.\n\t */\n\n\tnamespace: {\n\t get: function() {\n\t\treturn this._api_cfg.namespace;\n\t }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#data_names\n\t * @description Getter for the **data_names** configuration property.\n\t * @return {String} Returns the value of the **data_names** property in the API config object.\n\t */\n\n\tdata_names: {\n\t get: function() {\n\t\treturn this._api_cfg.data_names;\n\t }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#response\n\t * @description Getter for the last response returned by the server.\n\t * @return {Object} Returns the last response returned by the server.\n\t */\n\n\tresponse: {\n\t get: function() {\n\t\treturn this._response;\n\t }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#error\n\t * @description Getter for the last error returned by the server.\n\t * @return {Object} Returns the last error returned by the server.\n\t */\n\n\terror: {\n\t get: function() {\n\t\treturn this._error;\n\t }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#pagination_controls\n\t * @description Accessors for pagination_controls.\n\t * The getter returns a hash containing key/value pairs:\n\t * - *_s* is an integer containing the page size (how many results are returned by the query).\n\t * - *_p* is an integer containing the 1-based index of the _next_ page to load.\n\t * For example, a value of 3 indicates that this is the _third_ page loaded.\n\t *\n\t * The setter takes a hash with the same two key/value pairs, the string `'init'`, or\n\t * `null`; a value of `'init'` sets the default control values; any other value\n\t * (including *null*) disables use of the pagination controls.\n\t */\n\n\tpagination_controls: {\n\t get: function() {\n\t\treturn this._pagination_controls;\n\t },\n\t set: function(pg) {\n\t\tif (_.isObject(pg))\n\t\t{\n\t\t this._pagination_controls = pg;\n\t\t}\n\t\telse if (_.isString(pg) && (pg == 'init'))\n\t\t{\n\t\t this._pagination_controls = this.initial_pagination_controls;\n\t\t}\n\t\telse\n\t\t{\n\t\t this._pagination_controls = null;\n\t\t}\n\t }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#initial_pagination_controls\n\t * @description Get the initial pagination_controls.\n\t *\n\t * @return {Object} Returns a hash containing key/value pairs:\n\t * - *_s* is an integer containing the page size (how many results are returned by\n\t * the query). The value returned is 20.\n\t * - *_p* is an integer containing the 1-based index of the _next_ page to load.\n\t * For example, a value of 3 indicates that this is the _third_ page loaded.\n\t * The value returned is 1.\n\t */\n\n\tinitial_pagination_controls: {\n\t get: function() {\n\t\treturn { _s: 20, _p: 1 };\n\t }\n\t}\n },\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#setConfig\n\t * @description Sets initial values for the service configuration (the **srv_cfg**\n\t * argument to various instance methods).\n\t *\n\t * @param {Object} srv_cfg The configuration to merge into the existing state, or to\n\t * completely replace the existing configuration.\n\t * @param {Boolean} replace If `true`, the *srv_cfg* value replaces the current configuration;\n\t * otherwise, the content of *srv_cfg* are merged into the current ones.\n\t */\n\n\tsetConfig: function(srv_cfg, replace) {\n\t if (replace)\n\t {\n\t\tthis._srv_cfg = _.merge({ }, srv_cfg);\n\t }\n\t else\n\t {\n\t\tthis._srv_cfg = _.merge(this._srv_cfg, srv_cfg);\n\t }\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#getConfig\n\t * @description Gets the current configuration.\n\t *\n\t * @return {Object} Returns a copy of the current configuration.\n\t */\n\n\tgetConfig: function() {\n\t return _.merge({ }, this._srv_cfg);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#url_path_for\n\t * @description Generates the path component of the URL for the given action.\n\t * This includes processing the root URL template, interpolating the replacement directives, and\n\t * adding action-specific components to the path.\n\t *\n\t * @param {String} action The name of the action. The base implementation supports the standard\n\t * Rails actions `index`, `create`, `show`, `update`, and `destroy`; subclasses can augment this set\n\t * as needed.\n\t * @param {Object|Integer|String} [target] Some actions need additional context for the URL; for example,\n\t * a target object whose identifier to place in the path.\n\t * The value of this parameter is really unspecified, and is interpreted by subclass implementations as\n\t * needed; typically, it is either an object that contains an **id** property, or the identifier itself.\n\t * Some services may need to pack a number of URL parameters (dynamic segments) into a single object\n\t * to pass in this parameters.\n\t * \n\t * @return {String|null} Returns the URL path for the action; if *action* is not supported,\n\t * returns `null`.\n\t */\n\n\turl_path_for: function(action, target) {\n\t let root_path = this._expand_url_template(this.root_url_template);\n\n\t let tid = (_.isUndefined(target)) ? undefined : this._id(target);\n\n\t if ((action == 'index') || (action == 'create'))\n\t {\n\t\treturn root_path + '.json';\n\t }\n\t else if ((action == 'show') || (action == 'update') || (action == 'destroy'))\n\t {\n\t\treturn root_path + '/' + tid + '.json';\n\t }\n\t else\n\t {\n\t\treturn null;\n\t }\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#get\n\t * @description Execute a `GET` method.\n\t * This method is more or less a straight passthrough to the Axios `get` method.\n\t *\n\t * @param {String} url The target URL.\n\t * @param {Object} [config] Configuration object to pass to the Axios `get` method; this object\n\t * is merged into the default HTTP configuration object.\n\t *\n\t * @return {Promise} Returns a promise that resolves or rejects based on the return value\n\t * from the Axios `get` method.\n\t * The error and response objects are also saved in the {@sref FlAPIService#error} and \n\t * {@sref FlAPIService#response} properties, respectively.\n\t */\n\n\tget: function(url, config) {\n\t let self = this;\n\n\t return this._http_service.get(url, this._make_config(config))\n\t\t.then(function(r) {\n \t\t self._error = null;\n\t\t self._response = r;\n\t\t return Promise.resolve(r);\n\t\t})\n\t\t.catch(function(e) {\n\t\t self._error = e;\n\t\t self._response = e.response;\n\t\t return Promise.reject(e);\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#post\n\t * @description Execute a `POST` method.\n\t * The actual call is to {@sref FlAPIService#process}, which then dispatches to the\n\t * Axios `post` method. As a consequence, the special processing implemented by\n\t * {@sref FlAPIService#process} is triggered; for example, the XSRF header is added to the\n\t * headers list if the **xsrfToken** configuration property is non-nil.\n\t *\n\t * @param {String} url The target URL.\n\t * @param {Object} data The data to submit to the server; note that, differently from the \"action\"\n\t * methods {@sref FlAPIService#create} and {@sref FlAPIService#update}, the value of *data* is not\n\t * wrapped inside the namespace.\n\t * @param {Object} [config] Configuration object to pass to axios.post; this object is\n\t * merged into the default service configuration.\n\t *\n\t * @return {Promise} Returns a promise that resolves or rejects based on the return value\n\t * from the Axios `post` method.\n\t * The response object is also saved in the {@sref FlAPIService#response} property.\n\t */\n\n\tpost: function(url, data, config) {\n\t return this.process('post', url, data, config);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#put\n\t * @description Execute a `PUT` method.\n\t * The actual call is to {@sref FlAPIService#process}, which then dispatches to the\n\t * Axios `put` method. As a consequence, the special processing implemented by\n\t * {@sref FlAPIService#process} is triggered; for example, the XSRF header is added to the\n\t * headers list if the **xsrfToken** configuration property is non-nil.\n\t *\n\t * @param {String} url The target URL.\n\t * @param {Object} data The data to submit to the server; note that, differently from the \"action\"\n\t * methods {@sref FlAPIService#create} and {@sref FlAPIService#update}, the value of *data* is not\n\t * wrapped inside the namespace.\n\t * @param {Object} [config] Configuration object to pass to axios.put; this object is\n\t * merged into the default service configuration.\n\t *\n\t * @return {Promise} Returns a promise that resolves or rejects based on the return value\n\t * from the Axios `put` method.\n\t * The response object is also saved in the {@sref FlAPIService#response} property.\n\t */\n\n\tput: function(url, data, config) {\n\t return this.process('put', url, data, config);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#patch\n\t * @description Execute a `PATCH` method.\n\t * The actual call is to {@sref FlAPIService#process}, which then dispatches to the\n\t * Axios `patch` method. As a consequence, the special processing implemented by\n\t * {@sref FlAPIService#process} is triggered; for example, the XSRF header is added to the\n\t * headers list if the **xsrfToken** configuration property is non-nil.\n\t *\n\t * @param {String} url The target URL.\n\t * @param {Object} data The data to submit to the server; note that, differently from the \"action\"\n\t * methods {@sref FlAPIService#create} and {@sref FlAPIService#update}, the value of *data* is not\n\t * wrapped inside the namespace.\n\t * @param {Object} [config] Configuration object to pass to axios.patch; this object is\n\t * merged into the default service configuration.\n\t *\n\t * @return {Promise} Returns a promise that resolves or rejects based on the return value\n\t * from the Axios `patch` method.\n\t * The response object is also saved in the {@sref FlAPIService#response} property.\n\t */\n\n\tpatch: function(url, data, config) {\n\t return this.process('patch', url, data, config);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#delete\n\t * @description Execute a `DELETE` method.\n\t * The actual call is to {@sref FlAPIService#process}, which then dispatches to the\n\t * Axios `delete` method. As a consequence, the special processing implemented by\n\t * {@sref FlAPIService#process} is triggered; for example, the XSRF header is added to the\n\t * headers list if the **xsrfToken** configuration property is non-nil.\n\t *\n\t * @param {String} url The target URL.\n\t * @param {Object} [data] Data to send; this is typically an empty object.\n\t * @param {Object} [config] Configuration object to pass to axios.delete; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return On success, returns a resolved promise containing the response data.\n\t * On error, returns a rejected promise containing the response.\n\t * In all cases, the response object is also saved int the {@sref FlAPIService#response}\n\t * property.\n\t */\n\n\tdelete: function(url, data, config) {\n\t return this.process('delete', url, data, config);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#head\n\t * @description Execute a `HEAD` method.\n\t * This method is more or less a straight passthrough to the Axios `head` method.\n\t *\n\t * @param {String} url The target URL.\n\t * @param {Object} [config] Configuration object to pass to the Axios `head` method; this object\n\t * is merged into the default HTTP configuration object.\n\t *\n\t * @return {Promise} Returns a promise that resolves or rejects based on the return value\n\t * from the Axios `head` method.\n\t * The error and response objects are also saved in the {@sref FlAPIService#error} and \n\t * {@sref FlAPIService#response} properties, respectively.\n\t */\n\n\thead: function(url, config) {\n\t let self = this;\n\t \n\t return this._http_service.head(url, this._make_config(config))\n\t\t.then(function(r) {\n\t\t self._error = null;\n\t\t self._response = r;\n\t\t return Promise.resolve(r);\n\t\t})\n\t\t.catch(function(e) {\n\t\t self._error = e;\n\t\t self._response = e.response;\n\t\t return Promise.reject(e);\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#index\n\t * @description Make an :index call by calling `axios.get` against the root URL.\n\t *\n\t * @param {Object} [params] Parameters to pass in the request; the contents of this object are\n\t * merged into *config.params*, and eventually make their way to the query string.\n\t * @param {Object} [config] Configuration object to pass to `axios.get`; this object is\n\t * merged into the default HTTP configuration object.\n\t *\n\t * @return On success, returns a resolved promise containing the response data converted\n\t * to an array of model objects.\n\t * On error, returns a promise that rejects with the value\n\t * from the {@sref FlAPIService#get} method.\n\t * The error and response objects are also saved in the {@sref FlAPIService#error} and \n\t * {@sref FlAPIService#response} properties, respectively.\n\t */\n\n\tindex: function(params, config) {\n\t let self = this;\n\n\t return this.get(this.url_path_for('index'), this._make_index_config(params, config))\n\t\t.then(function(r) {\n\t\t self._set_pagination_controls(r);\n\t\t return Promise.resolve(self.modelFactory.create(self.response_data(r)));\n\t\t})\n\t\t.catch(function(e) {\n\t\t return Promise.reject(self.response_error(e));\n\t\t});\n\t},\n\t\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#setShowDidSucceed\n\t * @description Register a callback for the :show action.\n\t * This function is called on a successful :show action; it takes one argument, the\n\t * model object created from the response from the `axios.get` call.\n\t *\n\t * @param {Function} cb A function that will be installed as the :show callback.\n\t * Set it to `null` to disable it (this is the default value).\n\t * This function can modify the model object before it is returned by the :show action.\n\t */\n\n\tsetShowDidSucceed: function(cb) {\n\t this._showDidSucceed = cb;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#_create_or_refresh_from_id\n\t * @description Refresh an existing model instance, or create a new one.\n\t * This (internal) method is used in action implementations where the API returns object data,\n\t * such as for the `show` and `update` actions.\n\t * If those implementations are called with a model instance in the *id* parameter, then the\n\t * client has provided the target instance explicitly, and the implementation should use it;\n\t * in this case, the method simply calls `refres` on it.\n\t * Otherwise, it calls {@sref FlModelFactory#create} to convert *data* to an object instance.\n\t * Since model instances are cached, this only makes a difference if the target instance had\n\t * been created explicitly, rather than via the {@sref FlModelFactory#create} method: in this case,\n\t * the instance may not be cached, and using `create` would result in two copies of the\n\t * object floating around in the system. Use of this method helps avoiding that kind of problem.\n\t *\n\t * @param {Integer|String|Object} id A string or integer containing the identifier, or a model\n\t * instance from which the identifier is obtained.\n\t * @param {Object} data The model data to use for the refresh or create.\n\t *\n\t * @return Returns the object that was refreshed: if *id* is an identifier, it returns the\n\t * object that was created by a call to {@sref FlModelFactory#create}; if it is a model instance,\n\t * it returns *id*.\n\t */\n\n\t_create_or_refresh_from_id: function(id, data) {\n\t if (!_.isNil(id) && !_.isNil(id.__class) && _.isFunction(id.refresh))\n\t {\n\t\t// This looks like a model instance, so just refresh it.\n\n\t\tid.refresh(data);\n\t\treturn id;\n\t }\n\t else\n\t {\n\t\treturn this.modelFactory.create(data);\n\t }\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#show\n\t * @description Make a :show call by calling `axios.get` against the root URL/:id.\n\t *\n\t * @param {Integer|String|Object} id A string or integer containing the identifier to append to\n\t * the root URL. You can also pass an object with an `id` property, whose value will be used\n\t * for the identifier; this makes it possible to pass model instances to the method.\n\t * @param {Object} [params] Parameters to pass in the request; the contents of this object are\n\t * merged into *config.params*, and eventually make their way to the query string.\n\t * @param {Object} [config] Configuration object to pass to `axios.get`; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return On success, returns a resolved promise containing the response data converted to a\n\t * model object.\n\t * On error, returns a promise that rejects with the value\n\t * from the {@sref FlAPIService#get} method.\n\t * The error and response objects are also saved in the {@sref FlAPIService#error} and \n\t * {@sref FlAPIService#response} properties, respectively.\n\t */\n\n\tshow: function(id, params, config) {\n\t let self = this;\n\t return this.get(this.url_path_for('show', id), this._make_get_config(params, config))\n\t\t.then(function(r) {\n\t\t let model = self._create_or_refresh_from_id(id, self.response_data(r));\n\n\t\t if (_.isFunction(self._showDidSucceed))\n\t\t {\n\t\t\tself._showDidSucceed.call(self, model);\n\t\t }\n\t\t return Promise.resolve(model);\n\t\t})\n\t\t.catch(function(e) {\n\t\t return Promise.reject(self.response_error(e));\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#process\n\t * @description Make a processing call; this is the method that the high level\n\t * processing methods (**create**, **update**, **delete**) call.\n\t * A processing call causes the state of the server to change: a :create, :update, or\n\t * :destroy call (which are executed via a `POST`, `PATCH`, or `DELETE` method,\n\t * respectively). The `PUT` method is also supported, althoug the Rails API uses `PATCH`\n\t * now for updates.\n\t *\n\t * If the **xsrfToken** property is defined, an XSRF header is generated.\n\t * The method also checks if the _data_ contain file objects, and if so sets up the `axios`\n\t * service to submit data in multipart form.\n\t *\n\t * @param {String} method The method to use: `post`, `patch`, `put`, `delete`.\n\t * @param {String} url The URL of the server endpoint.\n\t * @param {Object} data The data to submit to the server; see above for a discussion of\n\t * how the data are submitted.\n\t * @param {Object} [config] Configuration object to pass to axios.patch; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return {Promise} Returns a promise that resolves or rejects based on the return value\n\t * from the supported Axios processing methods.\n\t * It also returns a rejected promise if *method* is not the name of a supported method.\n\t * The error and response objects are also saved in the {@sref FlAPIService#error} and \n\t * {@sref FlAPIService#response} properties, respectively.\n\t */\n\n\tprocess: function(method, url, data, config) {\n\t let self = this;\n\t let api_data = data;\n\t let cfg = this._make_config(config);\n\t let args;\n\t let um = method.toLowerCase();\n\n\t if (!_.isNil(self.xsrfToken))\n\t {\n\t\t_.merge(cfg, { headers: { [self.xsrfHeaderName]: self.xsrfToken } });\n\t }\n\n\t if (self._has_file_item(api_data))\n\t {\n\t\tself._add_content_type(cfg, undefined);\n\t\tlet flat = { };\n\t\tself._flatten_data(api_data, flat, '');\n\t\tapi_data = self._form_data(flat);\n\t }\n\n\t let m;\n\t if (um == 'post')\n\t {\n\t\tm = this._http_service.post;\n\t\targs = [ url, api_data, cfg ];\n\t }\n\t else if (um == 'patch')\n\t {\n\t\tm = this._http_service.patch;\n\t\targs = [ url, api_data, cfg ];\n\t }\n\t else if (um == 'put')\n\t {\n\t\tm = this._http_service.put;\n\t\targs = [ url, api_data, cfg ];\n\t }\n\t else if (um == 'delete')\n\t {\n\t\tm = this._http_service.delete;\n\t\targs = [ url, cfg ];\n\t }\n\t else\n\t {\n\t\tm = null;\n\t }\n\n\t if (m)\n\t {\n\t\treturn m.apply(this._http_service, args)\n\t\t .then(function(r) {\n\t\t\tself._error = null;\n\t\t\tself._response = r;\n\t\t\treturn Promise.resolve(r);\n\t\t })\n\t\t .catch(function(e) {\n\t\t\tself._error = e;\n\t\t\tself._response = e.response;\n\t\t\treturn Promise.reject(e);\n\t\t });\n\t }\n\t else\n\t {\n\t\treturn Promise.reject('unsupported processing method: ' + method);\n\t }\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#create\n\t * @description Make a :create call by calling `axios.post` against the root URL.\n\t * The actual call is to {@sref FlAPIService#process}, which then dispatches to `axios.post`.\n\t *\n\t * @param {Object} data The data to submit to the server. The object contains two properties,\n\t * **wrapped** and **unwrapped**. See {@sref FlAPIService#_wrap_data} for details.\n\t * @param {Object} [config] Configuration object to pass to axios.post; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return On success, returns a resolved promise containing the response data.\n\t * On error, returns a promise that rejects with the value\n\t * from the {@sref FlAPIService#post} method.\n\t * The error and response objects are also saved in the {@sref FlAPIService#error} and \n\t * {@sref FlAPIService#response} properties, respectively.\n\t */\n\n\tcreate: function(data, config) {\n\t let self = this;\n\t \n\t return this.post(this.url_path_for('create'), this._wrap_data(data), config)\n\t\t.then(function(r) {\n\t\t return Promise.resolve(self.modelFactory.create(self.response_data(r)));\n\t\t})\n\t\t.catch(function(e) {\n\t\t return Promise.reject(self.response_error(e));\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#update\n\t * @description Make a :update call by calling `axios.patch` against the root URL/:id.\n\t * The actual call is to {@sref FlAPIService#process}, which then dispatches to `axios.patch`.\n\t *\n\t * @param {Integer|String|Object} id A string or integer containing the identifier to append to\n\t * the root URL. You can also pass an object with an `id` property, whose value will be used\n\t * @param {Object} data The data to submit to the server. The object contains two properties,\n\t * **wrapped** and **unwrapped**. See {@sref FlAPIService#_wrap_data} for details.\n\t * @param {Object} [config] Configuration object to pass to axios.patch; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return On success, returns a resolved promise containing the response data.\n\t * On error, returns a promise that rejects with the value\n\t * from the {@sref FlAPIService#patch} method.\n\t * The error and response objects are also saved in the {@sref FlAPIService#error} and \n\t * {@sref FlAPIService#response} properties, respectively.\n\t */\n\n\tupdate: function(id, data, config) {\n\t let self = this;\n\n\t return this.patch(this.url_path_for('update', id), this._wrap_data(data), config)\n\t\t.then(function(r) {\n\t\t return Promise.resolve(self._create_or_refresh_from_id(id, self.response_data(r)));\n\t\t})\n\t\t.catch(function(e) {\n\t\t return Promise.reject(self.response_error(e));\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#destroy\n\t * @description Make a :destroy call by calling `axios.delete` against the root URL/:id.\n\t * The actual call is to {@sref FlAPIService#process}, which then dispatches to `axios.delete`.\n\t *\n\t * @param {Integer|String|Object} id A string or integer containing the identifier to append to\n\t * the root URL. You can also pass an object with an `id` property, whose value will be used\n\t * for the identifier; this makes it possible to pass model instances to the method.\n\t * @param {Object} [config] Configuration object to pass to axios.delete; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return On success, returns a resolved promise containing the response data.\n\t * On error, returns a promise that rejects with the value\n\t * from the {@sref FlAPIService#delete} method.\n\t * The error and response objects are also saved in the {@sref FlAPIService#error} and \n\t * {@sref FlAPIService#response} properties, respectively.\n\t */\n\n\tdestroy: function(id, config) {\n\t let self = this;\n\t return this.delete(this.url_path_for('destroy', id), { }, config)\n\t\t.then(function(r) {\n\t\t return Promise.resolve(self.response_status(r));\n\t\t})\n\t\t.catch(function(e) {\n\t\t return Promise.reject(self.response_error(e));\n\t\t});\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#_make_config\n\t * @description Build configuration parameters for a call to Axios.\n\t *\n\t * Subclasses likely won't need to override this method.\n\t *\n\t * @param {Object} [config] Configuration object to pass to Axios; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return {Object} Returns a configuration object where the values in config have been\n\t * merged into this._srv_cfg.\n\t */\n\n\t_make_config: function(config) {\n\t if (!_.isObject(config)) config = {};\n\n\t return _.merge({}, this._srv_cfg, config);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#_make_get_config\n\t * @description Build configuration parameters for a `GET` method call to Axios.\n\t * The method first calls *_make_config*, and then merges the contents of *params* into the\n\t * configuration object.\n\t * It is meant to be used when setting up call parameters for a `GET` method, since *params*\n\t * are merged into *config.params*, and therefore will appear in the query string.\n\t *\n\t * Subclasses likely won't need to override this method.\n\t *\n\t * @param {Object} [params] Parameters to pass in the request; the contents of this object are\n\t * merged into *config.params*, and eventually make their way to the query string.\n\t * @param {Object} [config] Configuration object to pass to axios; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return {Object} Returns a configuration object where the values in _config_ have been\n\t * merged into the default HTTP configuration.\n\t */\n\n\t_make_get_config: function(params, config) {\n\t let cfg = this._make_config(config);\n\t if (_.isObject(params))\n\t {\n\t\tlet cfgp = (_.isObject(cfg.params)) ? cfg.params : {}; \n\t\tcfg.params = _.merge({}, cfgp, params);\n\t }\n\n\t return cfg;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#_make_index_config\n\t * @description Build configuration parameters for an :index call to Axios.\n\t * The method first calls *_make_get_config*, then tags on the pagination controls\n\t * if they are enabled.\n\t * It is a specialized method to be used with `GET` calls that map to an :index action.\n\t *\n\t * Subclasses likely won't need to override this method.\n\t *\n\t * @param {Object} [params] Parameters to pass in the request; the contents of this object are\n\t * merged into *config.params*, and eventually make their way to the query string.\n\t * @param {Object} [config] Configuration object to pass to axios; this object is\n\t * merged into the default HTTP configuration.\n\t *\n\t * @return {Object} Returns a configuration object where the values in _config_ have been\n\t * merged into the default HTTP configuration.\n\t * Also, the pagination controls are placed in the\n\t * submission parameters if enabled. The first key name in the pagination control keys\n\t * array is used as the key.\n\t */\n\n\t_make_index_config: function(params, config) {\n\t let cfg = this._make_get_config(params, config);\n\n\t if (this.pagination_controls)\n\t {\n\t\tif (!_.isObject(cfg.params)) cfg.params = { };\n\t\t\n\t\t// The pagination controls are the starting set; if *params* contains :_pg, use that\n\t\t// value to override defaults\n\t\t\n\t\tlet k = this._pg_names[0];\n\t\tlet pg = (_.isObject(cfg.params._pg)) ? cfg.params._pg : { };\n\t\t\n\t\tcfg.params[k] = _.merge({}, this.pagination_controls, pg);\n\t }\n\n\t return cfg;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#_set_pagination_controls\n\t * @description Look for the pagination controls in the response data and extract them.\n\t * This method looks up all registered names for pagination controls and loads them\n\t * on the first hit.\n\t *\n\t * @param {Object} r The response object.\n\t */\n\n\t_set_pagination_controls: function(r) {\n\t let self = this;\n\t let data = r.data.payload;\n\t _.forEach(this._pg_names, function(k, idx) {\n\t\tif (!_.isUndefined(data[k]))\n\t\t{\n\t\t self.pagination_controls = data[k];\n\t\t return;\n\t\t}\n\t });\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#response_status\n\t * @description Extract a status object from a successful response.\n\t *\n\t * @param {Object} [r] The response object from Axios; if not provided, use the current internal value of the\n\t * response object, which was stored after the last successful API call.\n\t * Clients will typically call this method without arguments, in the `then` handler from an API call.\n\t *\n\t * @return {Object} Returns an object containing a status report:\n\t * - *:status* The response status.\n\t * - *:message* A string containing a status message.\n\t */\n\n\tresponse_status: function(r) {\n\t return FlAPIService.extract_response_status((_.isUndefined(r)) ? this._response : r);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#response_error\n\t * @description Extract or generate an error object from a failed response.\n\t * The method tries to detect the type of response: a general HTTP response,\n\t * an API error status, or an exception raised.\n\t *\n\t * @param {Object} [e] The error object from Axios; if not provided, use the current internal value of the\n\t * error object, which was stored after the last unsuccessful API call.\n\t * This object describes a failed request,\n\t * including situations where Axios was unable to submit the request (for example, because the\n\t * target URL is unavailable).\n\t * Clients will typically call this method without arguments, in the `catch` handler from an API call.\n\t *\n\t * @return {Object} Returns an object containing an error report:\n\t * - **type** The error type; if the response contains an **_error** object, this is the **type**\n\t * property. Otherwise, it is set to the response status code.\n\t * - **message** The error message; if the response contains an **_error** object, this is the **message**\n\t * property. Otherwise, it is set to the message from the response status code.\n\t */\n\n\tresponse_error: function(e) {\n\t return FlAPIService.extract_response_error((_.isUndefined(e)) ? this._response : e);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#response_data\n\t * @description Given a response, return the response data.\n\t * This method covers both successful and unsuccesful responses from the standard API.\n\t * It first checks that *response* is defined, since some requests may have failed before the\n\t * request is actually made (for example, if the server is down the connection is refused and\n\t * therefore there is no response).\n\t * It then checks if the *response.data* property is present, and looks for the two special\n\t * properties *response.data._error* and *response.data._status*, which are generated by the\n\t * API to indicate error or success; it returns *response.data._error* if present.\n\t * Otherwise, it checks for the presence of *response.data.payload*, and returns *response.data._status*\n\t * if *response.data.payload* is not present.\n\t * Finally, it iterates over the values in the **data_names** configuration property,\n\t * looking for a property by that name in *response.data.payload*; the first hit is returned.\n\t *\n\t * Most subclasses won't need to override this method.\n\t *\n\t * @param {Object} response The response, which should contain a **data** property.\n\t *\n\t * @return {Object|undefined} Returns the response data as described above; if *response* is\n\t * not an object, or if it does not contain the **data** property, it returns `undefined`.\n\t */\n\n\tresponse_data: function(response) {\n\t if (!_.isObject(response)) return undefined;\n\n\t let data = response.data;\n\t if (!_.isObject(data)) return undefined;\n\t \n\t if (!_.isUndefined(data._error)) return data._error;\n\n\t if (_.isObject(data.payload))\n\t {\n\t\tlet payload = data.payload;\n\t\tlet ary = this._api_cfg.data_names;\n\n\t\tif (ary)\n\t\t{\n\t\t let idx;\n\t\t let len = ary.length;\n\t\t let name;\n\n\t\t for (idx=0 ; idx < len ; idx++)\n\t\t {\n\t\t\tname = ary[idx];\n\t\t\tif (payload[name])\n\t\t\t{\n\t\t\t return payload[name];\n\t\t\t}\n\t\t }\n\t\t}\n\t }\n\t else if (!_.isUndefined(data._status))\n\t {\n\t\treturn data._status;\n\t }\n\t \n\t return null;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#_expand_url_template\n\t * @description Process a URL template, interpolate the replacement directives, and return\n\t * the expanded URL.\n\t * This method scans the contents of *tpl* for interpolation directives, which it expands in the\n\t * context of `this`, and inserts the value of the directive in the template; see the class\n\t * documentation for details.\n\t * @param {String} tpl The template to process.\n\t * @return {String} Returns the URL generated from the template and the state of the service\n\t * object.\n\t */\n\n\t_expand_url_template: function(tpl) {\n\t let self = this;\n\t let pre;\n\t let rest = tpl;\n\t let fragments = new Array();\n\t let idx = 0;\n\t let fdx;\n\t let expr;\n\t \n\t while (idx >= 0)\n\t {\n\t\tidx = rest.indexOf('${');\n\t\tif (idx < 0)\n\t\t{\n\t\t // no more replacement directives: we are done\n\n\t\t fragments.push(rest);\n\t\t}\n\t\telse\n\t\t{\n\t\t fragments.push(rest.substring(0, idx));\n\t\t fdx = rest.indexOf('}', idx);\n\t\t if (fdx < 0) fdx = rest.length;\n\t\t fragments.push(_.get(self, rest.substring(idx+2, fdx)));\n\t\t rest = rest.substring(fdx+1);\n\t\t}\n\t }\n\n\t return fragments.join('');\n\t},\n\n\t_has_file_item: function(data) {\n\t let k;\n\t let v;\n\t let self = this;\n\n\t for (k in data)\n\t {\n\t\tv = data[k];\n\n\t\t// File is defined in a browser environment, but not in Node.js.\n\t\t// We skip this test if File is not defined\n\n\t\ttry {\n\t\t if (v instanceof(File)) return true;\n\t\t} catch (x) {\n\t\t}\n\n\t\tif (_.isObject(v))\n\t\t{\n\t\t if (self._has_file_item(v))\n\t\t {\n\t\t\treturn true;\n\t\t }\n\t\t}\n\t }\n\n\t return false;\n\t},\n\n\t_flatten_data: function(data, f, root) {\n\t let self = this;\n\n\t _.forEach(data, function(v, k) {\n\t\tlet fk = (root.length > 0) ? (root + '[' + k + ']') : k;\n\n\t\tif (v instanceof(File))\n\t\t{\n\t\t f[fk] = v;\n\t\t}\n\t\telse if (_.isObject(v))\n\t\t{\n\t\t self._flatten_data(v, f, fk);\n\t\t}\n\t\telse\n\t\t{\n\t\t f[fk] = v;\n\t\t}\n\t });\n\t},\n\n\t_form_data: function(data) {\n\t let fd = new FormData();\n\t let self = this;\n\n\t _.forEach(data, function(v, k) {\n\t\tif (v instanceof(File))\n\t\t{\n\t\t fd.append(k, v, v.name);\n\t\t}\n\t\telse\n\t\t{\n\t\t fd.append(k, v);\n\t\t}\n\t });\n\t return fd;\n\t},\n\n\t_add_content_type: function(cfg, ct) {\n\t if (_.isObject(cfg.headers))\n\t {\n\t\tcfg.headers['Content-Type'] = ct;\n\t }\n\t else\n\t {\n\t\tcfg.headers = { 'Content-Type': ct };\n\t }\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#_id\n\t * @description Converts an identifier parameter to an identifier value.\n\t * if *id* is an object with a non-null **id** property, the value of `id.id` is returned.\n\t * Otherwise, the value of *id* is returned as is.\n\t *\n\t * @param {Integer|String|Object} id A string or integer containing the identifier.\n\t * You can also pass an object with an `id` property, whose value will be used\n\t * for the identifier; this makes it possible to pass model instances to the method.\n\t */\n\n\t_id: function(id) {\n\t return (_.isObject(id) && _.has(id, 'id') && !_.isNil(id.id)) ? id.id : id;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#_wrap_data\n\t * @description Wrap submission data within the namespace if one is defined.\n\t * The *data* object contains two optional properties,\n\t * **wrapped** and **unwrapped**. The **wrapped** property is also an object that contains\n\t * data to be placed inside the service's namespace, so that the actual data will be in a\n\t * property named after the namespace. The **unwrapped** property is also an object, and is\n\t * merged into the submission data as-is.\n\t * For example, if the contents of *data* are\n\t * ```\n\t * {\n\t * wrapped: { p1: 10 },\n\t * unwrapped: { other: 20 }\n\t * }\n\t * ```\n\t * and the namespace is `ns`, then the return value is\n\t * ```\n\t * {\n\t * ns: { p1: 10 },\n\t * other: 20\n\t * }\n\t * ```\n\t *\n\t * A common unwrapped property is **to_hash**, whose value is an object of configuration\n\t * options for the server method that generates a hash representation of a Ruby model; for\n\t * example, to get the verbose representation of an object:\n\t * ```\n\t * let srv = new MyAPIService();\n\t * srv\n\t * .show(123456, { unwrapped: { to_hash: { verbosity: 'verbose' } } })\n\t * .then(function(o) {\n\t * // process the returned object\n\t * });\n\t * ```\n\t *\n\t * @param {Object} data The data to submit to the server. The object contains two properties,\n\t * **wrapped** and **unwrapped**, which are processed as described above.\n\t *\n\t * @return {Object} If the namespace is defined, the return value is an object with one\n\t * property, the namespace, whose value is *data*. If no namespace is defined, then\n\t * *data* is returned.\n\t */\n\n\t_wrap_data: function(data) {\n\t let api_data = { };\n\n\t if (_.isObject(data.unwrapped))\n\t {\n\t\t_.merge(api_data, data.unwrapped);\n\t }\n\n\t if (_.isObject(data.wrapped))\n\t {\n\t\tif (this.namespace)\n\t\t{\n\t\t api_data[this.namespace] = data.wrapped;\n\t\t}\n\t\telse\n\t\t{\n\t\t _.merge(api_data, data.wrapped);\n\t\t}\n\t }\n\t \n\t return api_data;\n\t}\n },\n class_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#modelFactory\n\t * @classproperty\n\t * @description Getter for **modelFactory** property.\n\t * This property is just an accessor for the `modelFactory` in the current configuration.\n\t *\n\t * @return {String} Returns the value of the **modelFactory** property in the object.\n\t */\n\n\tmodelFactory: {\n\t get: function() { return this._srv_cfg.modelFactory; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#xsrfCookieName\n\t * @classproperty\n\t * @description Accessor for the name of the XSRF cookie from the current configuation\n\t * defaults. This property is just an accessor for the `xsrfCookieName` configuration property.\n\t *\n\t * @param {String} name The name of the cookie to use as a value for the XSRF token.\n\t *\n\t * @return {String} The getter returns the name of the XSRF cookie from the current configuation\n\t * defaults.\n\t */\n\n\txsrfCookieName: {\n\t get: function() { return this._srv_cfg.xsrfCookieName; },\n\t set: function(name) { this._srv_cfg.xsrfCookieName = name; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#xsrfHeaderName\n\t * @classproperty\n\t * @description Accessor for the name of the http header that carries the XSRF token value,\n\t * from the current configuation defaults.\n\t * This property is just an accessor for the `xsrfHeaderName` configuration property.\n\t *\n\t * @param {String} name The name of the http header that carries the XSRF token value.\n\t *\n\t * @return {String} The getter returns the name of the XSRF header from the current configuation\n\t * defaults.\n\t */\n\n\txsrfHeaderName: {\n\t get: function() { return this._srv_cfg.xsrfHeaderName; },\n\t set: function(name) { this._srv_cfg.xsrfHeaderName = name; }\n\t},\n\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#xsrfToken\n\t * @classproperty\n\t * @description Accessor for the default (current) value of the XSRF token.\n\t * This property is the global, applicationwide, XSRF token. Instances of {@sref FlAPIService}\n\t * may override this value, but typically won't.\n\t *\n\t * @param {String} token The new value of the token.\n\t *\n\t * @return {String} The getter returns the current value of the global XSRF token.\n\t */\n\n\txsrfToken: {\n\t get: function() { return this._srv_cfg.xsrfToken; },\n\t set: function(token) { this._srv_cfg.xsrfToken = token; }\n\t}\n },\n class_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#setServiceConfig\n\t * @classmethod\n\t * @description Sets default values for the service configuration (the **srv_cfg**\n\t * argument to various instance methods).\n\t *\n\t * @param {Object} srv_cfg The configuration to merge into the existing defaults, or to\n\t * completely replace the existing defaults.\n\t * @param {Boolean} replace If `true`, the *srv_cfg* value replaces the current defaults;\n\t * otherwise, the content of *srv_cfg* are merged into the current defaults.\n\t */\n\n\tsetServiceConfig: function(srv_cfg, replace) {\n\t if (replace)\n\t {\n\t\tthis._srv_cfg = _.merge({ }, srv_cfg);\n\t }\n\t else\n\t {\n\t\tthis._srv_cfg = _.merge(this._srv_cfg, srv_cfg);\n\t }\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#getServiceConfig\n\t * @classmethod\n\t * @description Gets the current global service default configuration.\n\t *\n\t * @return {Object} Returns a copy of the current default configuration.\n\t */\n\n\tgetServiceConfig: function() {\n\t return _.merge({ }, this._srv_cfg);\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#extract_response_status\n\t * @classmethod\n\t * @description Extract a status object from a successful response.\n\t *\n\t * @param {Object} r The response object from Axios.\n\t *\n\t * @return {Object} Returns an object containing a status report:\n\t * - *:status* The response status.\n\t * - *:message* A string containing a status message.\n\t */\n\n\textract_response_status: function(r) {\n\t let s = {\n\t\tstatus: r.status\n\t };\n\n\t let rd = r.data;\n\t if (_.isObject(rd) && _.isObject(rd._status))\n\t {\n\t\ts = rd._status;\n\t }\n\t else\n\t {\n\t\ts.message = r.statusText;\n\t }\n\n\t return s;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIService#extract_response_error\n\t * @classmethod\n\t * @description Extract or generate an error object from a failed response.\n\t * The method tries to detect the type of response: a general HTTP response,\n\t * an API error status, or an exception raised.\n\t *\n\t * @param {Object} e The error object from Axios.\n\t * This object describes a failed request,\n\t * including situations where Axios was unable to submit the request (for example, because the\n\t * target URL is unavailable).\n\t *\n\t * @return {Object} Returns an object containing an error report:\n\t * - **type** The error type; if the response contains an **_error** object, this is the **type**\n\t * property. Otherwise, it is set to the response status code.\n\t * - **message** The error message; if the response contains an **_error** object, this is the **message**\n\t * property. Otherwise, it is set to the message from the response status code.\n\t */\n\n\textract_response_error: function(e) {\n\t let err = { };\n\t let response = e.response;\n\n\t if (_.isObject(response))\n\t {\n\t\tlet rd = response.data;\n\t\tif (_.isObject(rd) && _.isObject(rd._error))\n\t\t{\n\t\t // we must create a copy of the error object, to avoid circularities later on when we\n\t\t // assign err.response. The circular structure triggers JSON errors.\n\t\t \n\t\t err = _.merge({ }, rd._error);\n\t\t}\n\n\t\tif (_.isUndefined(err.type)) err.type = (_.isUndefined(response.status)) ? 'error' : response.status;\n\t\t\n\t\tif (_.isUndefined(err.message))\n\t\t{\n\t\t err.message = \"response error\";\n\t\t if (_.isString(response.statusText)) err.message = response.statusText;\n\t\t if (_.isString(response.message)) err.message = response.message;\n\n\t\t if (response.stack)\n\t\t {\n\t\t\terr.details = {\n\t\t\t stack: response.stack.split(\"\\n\")\n\t\t\t};\n\t\t }\n\t\t}\n\n\t\terr.response = response;\n\t }\n\t else if (_.isError(e))\n\t {\n\t\terr.message = e.message;\n\t\terr.type = e.name;\n\t\tif (e.stack)\n\t\t{\n\t\t err.details = {\n\t\t\tstack: e.stack.split(\"\\n\"),\n\t\t\terror: e\n\t\t };\n\t\t}\n\t }\n\n\t return err;\n\t}\n },\n extensions: [ ]\n});\n\nFlAPIService._srv_cfg = _.merge({ }, DEFAULT_SRV_CFG);\n\n/**\n * @ngdoc type\n * @name FlNestedAPIService\n * @extends FlAPIService\n * @module fl.api_services\n * @description FlNestedAPIService is the base class for API services that communicate with a\n * {@sref Rails-nested-resources Rails nested resource}.\n * This class modifies {@sref FlAPIService} to support the structure of nested resource APIs.\n * It manages both standard and shallow nested resources, based on the value of the configuration\n * variable **shallow_root_url_template**.\n *\n * Like for {@sref FlAPIService}, there are two ways to use this service:\n * 1. Create an instance of FlAPIService with appropriate configuration.\n * 2. Define a subclass that encapsulates the configuration and optionally also adds API-specific\n * entry points.\n *\n * See the documentation for {@sref FlAPIService} for a discussion of these two approaches; we recommend\n * creating subclasses.\n */\n\nlet FlNestedAPIService = FlClassManager.make_class({\n name: 'FlNestedAPIService',\n superclass: 'FlAPIService',\n /**\n * @ngdoc method\n * @name FlNestedAPIService#constructor\n * @description The constructor; called during `new` creation.\n * Note that subclasses are expected to pass the parent resource's object or identifier as\n * additional arguments.\n *\n * @param {Object} api_cfg Configuration for the API object; the following documentation lists\n * options that are specific to this class; for the common ones, see {@sref FlAPIService#constructor}.\n * @property {String} api_cfg.shallow_root_url_template The template used to generate the shallow\n * root URL. If this option is present, the instance expects that the Rails API uses a shallow\n * setup, where the `index` and `create` actions are nested within a parent resource, and\n * `show`, `update`, and `destroy` are scoped outside the parent.\n * @param {Object} srv_cfg Configuration for the service. See {@sref FlAPIService#constructor}\n * for details.\n */\n initializer: function(api_cfg, srv_cfg) {\n\tthis.__super_init('FlAPIService', api_cfg, srv_cfg);\n },\n instance_properties: {\n\t/**\n\t * @ngdoc property\n\t * @name FlAPIService#shallow_root_url_template\n\t * @description Getter for **shallow_root_url_template** configuration property.\n\t * @return {String} Returns the value of the **shallow_root_url_template** property in the API\n\t * config object. Note that a `null` or `undefined` return value implies that the API is not\n\t * shallow.\n\t */\n\n\tshallow_root_url_template: {\n\t get: function() {\n\t\treturn this._api_cfg.shallow_root_url_template;\n\t }\n\t}\n },\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name FlNestedAPIService#url_path_for\n\t * @description Overrides the base implementation to add support for shallow APIs.\n\t *\n\t * @param {String} action The name of the action. The implementation supports the standard\n\t * Rails actions `index`, `create`, `show`, `update`, and `destroy`; subclasses can augment this set\n\t * as needed.\n\t * @param {Object|Integer} [target] Some actions need a target object whose identifier to place\n\t * in the path. The value is either an object that contains a **id** property, or the\n\t * identifier itself.\n\t * \n\t * @return {String|null} Returns the URL path for the action; if *action* is not supported,\n\t * returns `null`.\n\t */\n\n\turl_path_for: function(action, target) {\n\t let tpl = this.shallow_root_url_template;\n\t \n\t // :index and :create are always nested\n\t \n\t if (_.isNil(tpl) || (action == 'index') || (action == 'create'))\n\t {\n\t\treturn this.__super('FlAPIService', 'url_path_for', action, target);\n\t }\n\t \n\t let root_path = this._expand_url_template(tpl);\n\t let tid = (_.isUndefined(target)) ? undefined : this._id(target);\n\n\t if ((action == 'show') || (action == 'update') || (action == 'destroy'))\n\t {\n\t\treturn root_path + '/' + tid + '.json';\n\t }\n\t else\n\t {\n\t\treturn null;\n\t }\n\t}\n },\n class_properties: {\n },\n class_methods: {\n },\n extensions: [ ]\n});\n\n/**\n * @ngdoc service\n * @name FlAPIServiceRegistry\n * @module fl.api_services\n * @requires FlModelFactory\n * @description FlAPIServiceRegistry is a service that implements a registry of API\n * services. Use this registry to associate a given API service with the object type\n * it manages.\n */\n\nlet FlAPIServiceRegistry = FlClassManager.make_class({\n name: 'FlAPIServiceRegistry',\n initializer: function() {\n\tthis._services = { };\n },\n instance_properties: {\n },\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIServiceRegistry#register\n\t * @description Register API services provided by a module for model factory services.\n\t * This function is typically called after an {@sref FlAPIService} subclass is defined,\n\t * to associate data types with API service classes.\n\t * For example, a module named **my_service** defines the API service `MyAPIService`,\n\t * which implements the API client for `My::Datum` resources.\n\t * The registration looks like this:\n\t * ```\n\t * let MyDatum = FlClassRegistry.make_class({\n\t * ...\n\t * });\n\t * FlModelFactory.defaultFactory().register('my_service', [\n\t * { service: MyDatum, class_name: 'My::Datum' }\n\t * ]);\n\t *\n\t * let MyAPIService = FlClassRegistry.make_class({\n\t * ...\n\t * });\n\t *\n\t * FlGlobalAPIServiceRegistry.register('my_service', {\n\t * 'MyAPIService': 'My::Datum'\n\t * });\n\t * ```\n\t *\n\t * @param {String} module The module name.\n\t * @param {Object} services A hash mapping the name of API services provided by the module\n\t * to model service names. Properties are API service names, and their values the\n\t * corresponding model service type name.\n\t */\n\n\tregister: function(module, services) {\n\t let self = this;\n\n\t _.forEach(services, function(sv, sk) {\n\t\tlet k = self._normalize_name(sv);\n\t\tif (self._services[k])\n\t\t{\n\t\t console.log(\"(FlAPIServiceRegistry): model service '\"\n\t\t\t\t+ sv + \"' is already registered with API service '\"\n\t\t\t\t+ self._services[k].api_service + \"'\");\n\t\t}\n\t\tself._services[k] = { module: module, api_service: sk };\n\t });\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIServiceRegistry#unregister\n\t * @description Remove an API service from the registry.\n\t *\n\t * @param {string} name The service name.\n\t */\n\n\tunregister: function(name) {\n\t let kk = null;\n\t let srv = _.find(this._services, function(s, k) {\n\t\tif (s.api_service == name)\n\t\t{\n\t\t kk = k;\n\t\t return true;\n\t\t}\n\t\telse\n\t\t{\n\t\t return false;\n\t\t}\n\t });\n\n\t if (kk) delete this._services[kk];\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIServiceRegistry#service_info\n\t * @description Given a model service name, return info about the corresponding API service.\n\t * Model services are subclasses of {@sref FlModelBase}.\n\t *\n\t * @param {String} name The model service name (for example, `MyDatum`), or the model\n\t * type name (for example, `My::Datum`) from an object's hash representation;\n\t * the colons will be stripped off.\n\t *\n\t * @return {Object} If *name* is registered, it returns an object\n\t * containing two properties: *module* is the module where the service resides,\n\t * and *api_service* is the name of the API service.\n\t */\n\n\tservice_info: function(name) {\n\t let n = this._normalize_name(name);\n\n\t return (_.isNil(this._services[n])) ? null : this._services[n];\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlAPIServiceRegistry#create\n\t * @description Given a model service name, return an instance of the\n\t * corresponding API service.\n\t * Model services are subclasses of {@sref FlModelBase}.\n\t * This method uses the class registry to fetch the service and return a new instance.\n\t *\n\t * The first argument, *name*, is used to look up the service constructor. All other arguments\n\t * are passed to the constructor using spread syntax (`...args`). This supports constructors\n\t * with arbitrary argument lists. For example, the constructor for a nested API service typically\n\t * accepts the resting resource and the server configuration; when using `create`, pass these two\n\t * in the argument list:\n\t * ```\n\t * const SRV_CFG = { };\n\t * let res = get_my_resource();\n\t * let srv = FlGlobalAPIServiceRegistry.create('MyNestedService', res, SRV_CFG);\n\t * ```\n\t *\n\t * @param {String} name The model service name (for example, `MyDatum`), or the model\n\t * type name (for example, `My::Datum`) from an object's hash representation;\n\t * the colons will be stripped off.\n\t * @param {any} [...args] All the other arguments in the method call are passed to the\n\t * constructor for the service.\n\t *\n\t * @return {Object} If *name* is registered, it returns an instance\n\t * of the corresponding API service.\n\t */\n\n\tcreate: function(name) {\n\t var info = this.service_info(name);\n\t if (info)\n\t {\n\t\tlet srv = FlClassManager.get_class(info.api_service);\n\t\tif (_.isNil(srv))\n\t\t{\n\t\t console.log(\"(FlAPIServiceRegistry): API service '\" + info.api_service\n\t\t\t\t+ \"' is not registered with the class manager\");\n\t\t return null;\n\t\t}\n\n\t\tlet args = Array.from(arguments);\n\t\targs.shift();\n\n\t\treturn new srv(...args);\n\t }\n\t else\n\t {\n\t\tconsole.log(\"(FlAPIServiceRegistry): no API service for modelizer '\" + name + \"'\");\n\t\treturn null;\n\t }\n\t},\n\n\t_normalize_name: function(s) {\n\t return s.replace(/::/g, '');\n\t}\n },\n class_methods: {\n },\n extensions: [ ]\n});\n\n/**\n * @ngdoc service\n * @name FlGlobalAPIServiceRegistry\n * @module fl.api_services\n * @description\n * The global model factory. This is an instance of {@sref FlAPIServiceRegistry} that is globally accessible\n * and can be used as the applicationwide API service registry.\n */\n\nconst FlGlobalAPIServiceRegistry = new FlAPIServiceRegistry();\n\nmodule.exports = { FlAPIService, FlNestedAPIService, FlAPIServiceRegistry, FlGlobalAPIServiceRegistry };\n","/**\n * @ngdoc module\n * @name fl.model_factory\n * @module fl\n * @requires fl.object_system\n * @description\n * Model factory\n * This module implements a factory of model object services.\n * It exports two services:\n * - {@sref FlModelCache}, a global cache of model instances.\n * - {@sref FlModelFactory}, a service that creates or refreshes model instances from hash representations.\n *\n * It also exports {@sref FlModelBase}, the base class for all model classes.\n */\n\nconst _ = require('lodash');\nconst jscache = require('js-cache');\nconst { FlExtensions, FlClassManager } = require('./object_system');\nconst { DateTime } = require('luxon');\n\n/**\n * @ngdoc type\n * @name FlModelBase\n * @module fl.model_factory\n * @extends FlRoot\n * @description\n * The base class for model services.\n *\n * A model service is an object that is instantiated once per existing instance of a data\n * object in the client. Model services are organized in a class hierarchy that tracks the class\n * organization of data objects in the server.\n * \n * ##### Managing data objects\n * \n * Each data class has a corresponding model service that inherits from FlModelBase and that defines\n * the basic API configuration, and optionally adds subclass-specific functionality.\n * Subclasses **must** define a class method called `type_class` that returns a string containing\n * the name of the data class the service supports. They also typically define a `create` class method\n * that returns a new instance of the class.\n * The general outline of such subclass runs along these lines:\n * 1. Define class name, superclass, and initializer:\n *
\n *  let MyDatum = FlClassManager.make_class({\n *    name: 'MyDatum',\n *    superclass: 'FlModelBase',\n *    initializer: function(data) {\n *      this.__super_init('FlModelBase', data);\n *      this.refresh(data);\n *    },
\n * 2. This is followed by new and overridden instance methods, for example:\n *
\n *    instance_methods: {\n *      refresh: function(data) {\n *        if (!this.__super('FlModelBase', 'refresh', data)) return false;\n *        // additional processing of the instance data ...\n *        return true;\n *      },\n *\n *      my_method: function(p1, p2) {\n *        return 'returns: ' + p1 + ' : ' + p2;\n *      }\n *    },
\n * 3. And, finally, define class methods and extensions (mixins):\n *
\n *     class_methods: {\n *       type_class: function() {\n *         return 'My::Datum';\n *       },\n *       create: function(data) {\n *         return FlClassManager.modelize('MyDatum', data);\n *       }\n *     },\n *     extensions: {\n *       core: FlExtensions.FlCoreExtension\n *     }\n *   });
\n * \n * An object instance is created as follows:\n *
\n *   let data = get_data_from_api_call();\n *   let obj = new MyDatum(data);\n * \n *   // or, use the FlClassManager.modelize function:\n *   let obj2 = FlClassManager.modelize('MyDatum', data);\n * \n *   // or, use the class method:\n *   let obj3 = MyDatum.create(data);\n * 
\n * Note that the initializer is called automatically when the object is created.\n * To make method calls on the object:\n *
\n *   let concat = obj.my_method('one', 'two');\n * 
\n * \n * @param {Object} data The data associated with the instance.\n */\n\nlet FlModelBase = FlClassManager.make_class({\n name: 'FlModelBase',\n initializer: function(data) {\n\tthis.__super_init('FlRoot');\n\tthis.refresh(data);\n },\n instance_methods: {\n\t/**\n\t * @ngdoc method\n\t * @name FlModelBase#refresh\n\t * @description Refresh the state of the instance based on the contents\n\t * of the hash representation of an object.\n\t * \n\t * This method also validates that a refresh does not change the class type and object\n\t * identifier, if they are already set. This check prevents clients for creating an instance\n\t * of a given model class, and later change its \"type\" to another class.\n\t * Note that subclasses that override this method **must** call the superclass implementation\n\t * in order to trigger these checks (and the core loading functionality).\n\t *\n\t * @param {Object} data An object containing a representation of the \n\t * server object. This representation may be partial.\n\t *\n\t * @return [Boolean] Returns `true` if the state was refreshed from *data*, `false* otherwise.\n\t * (In other words, returns `false` if it detected that the update time in *data* is older than\n\t * the object's current update time.) Subclasses should use the return value to decide if the\n\t * subclass-specific state should be refreshed. For example:\n\t *\n\t * ```\n\t * let MySub = FlClassManager.make_class({\n\t * name: 'MySub',\n\t * superclass: 'FlModelBase',\n\t *\n\t * initializer: function(data) {\n\t * this.__super_init('FlModelBase', data);\n\t * },\n\t * instance_properties: {\n\t * },\n\t * instance_methods: {\n\t * refresh: function(data) {\n\t * if (!this.__super('FlModelBase', 'refresh', data)) return false;\n\t *\n\t * // refresh the MySub-specific state here\n\t *\n\t * // make sure to return `true` so that subclasses can chain appropriately\n\t * return true;\n\t * }\n\t * }\n\t * });\n\t * ```\n\t *\n\t * @throws Throws an exception if the properties **type** and **fingerprint** already exist\n\t * in `this`, and their value is different from those in *data*.\n\t */\n\n\trefresh: function(data) {\n\t if (!_.isUndefined(this.type) && !_.isUndefined(data.type) && (this.type != data.type))\n\t {\n\t\tthrow new Error('type mismatch in model data refresh');\n\t }\n\t \n\t if (!_.isUndefined(this.fingerprint) && !_.isUndefined(data.fingerprint)\n\t\t&& (this.fingerprint != data.fingerprint))\n\t {\n\t\tthrow new Error('fingerprint mismatch in model data refresh');\n\t }\n\n\t let self = this;\n\t let updated_at = null;\n\t if (!_.isNil(data.updated_at)) {\n\t\tupdated_at = new Date(data.updated_at);\n\t\tif (!_.isNil(self.updated_at)) {\n\t\t let self_updated_at = (_.isDate(self.updated_at)) ? self.updated_at : new Date(self.updated_at);\n\t\t if (updated_at.getTime() < self_updated_at.getTime()) {\n\t\t\treturn false;\n\t\t }\n\t\t}\n\t }\n\t \n\t _.forEach(data, function(v, k) {\n\t\tself[k] = self._convert_value(v);\n\t });\n\n\t if (!_.isNil(data.created_at)) self.created_at = new Date(data.created_at);\n\t if (!_.isNil(updated_at)) self.updated_at = updated_at;\n\n\t return true;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlModelBase#has_permission\n\t * @description\n\t * Check if the object has granted a permission to the current user.\n\t * This method looks up the property **permissions**, and if present it then supports two\n\t * types of checks. If **permissions** is an object, and *op* is a property of **permissions**\n\t * with value `true`, then it returns `true`.\n\t * If **permissions** is an array that includes *op*, then it returns `true`.\n\t * Otherwise, it returns `false`.\n\t * \n\t * @param {String} op The name of the permission to check; for example, `read` or `write`.\n\t *\n\t * @return {Boolean} Returns `true` if permission is granted, `false` otherwise.\n\t */\n\n\thas_permission: function(op) {\n\t // We need to do the array check first because an array will also return true for isObject\n\n\t if (_.isArray(this.permissions))\n\t {\n\t\treturn _.includes(this.permissions, op);\n\t }\n\t else if (_.isObject(this.permissions))\n\t {\n\t\treturn (this.permissions[op] == true);\n\t }\n\t else\n\t {\n\t\treturn false;\n\t }\n\t},\n\n\t_convert_value: function(value) {\n\t let self = this;\n\t\t\n\t if (_.isArray(value))\n\t {\n\t\treturn _.map(value, function(av, aidx) {\n\t\t return self._convert_value(av);\n\t\t});\n\t }\n\t else if (_.isObject(value))\n\t {\n\t\treturn _.reduce(value, function(acc, ov, ok) {\n\t\t acc[ok] = self._convert_value(ov);\n\t\t return acc;\n\t\t}, { });\n\t }\n\t else\n\t {\n\t\treturn value;\n\t }\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlModelBase#_convert_JSON_value\n\t * @description\n\t * Convert a JSON representation to a Javascript value.\n\t * If *value* is a string: if it is the string `null`, convert to the `null` value; otherwise,\n\t * convert to Javascript via a call to `JSON.parse`.\n\t * If *value* is not a string, return it as is.\n\t * \n\t * @param {any} value The value to convert.\n\t *\n\t * @return {any} Returns the converted value.\n\t */\n\t\n\t_convert_JSON_value: function(value) {\n\t if (_.isString(value)) {\n\t\treturn (value == 'null') ? null : JSON.parse(value);\n\t }\n\n\t return value;\n\t},\n\n\t/**\n\t * @ngdoc method\n\t * @name FlModelBase#_convert_date_value\n\t * @description\n\t * Convert a datetime representation to a Javascript Date object.\n\t * If *value* is a string, use `luxon` to convert it to a Date; otherwise, return as is.\n\t * \n\t * @param {any} value The value to convert.\n\t *\n\t * @return {any} Returns the converted value.\n\t */\n\t\n\t_convert_date_value: function(value) {\n\t if (_.isString(value)) {\n\t\tlet l = DateTime.fromISO(value, { zone: 'utc' });\n\t\tif (l.isValid) return l.toJSDate();\n\n\t\tl = DateTime.fromRFC2822(value, { zone: 'utc' });\n\t\tif (l.isValid) return l.toJSDate();\n\n\t\tl = DateTime.fromHTTP(value, { zone: 'utc' });\n\t\tif (l.isValid) return l.toJSDate();\n\n\t\tl = DateTime.fromSQL(value, { zone: 'utc' });\n\t\tif (l.isValid) return l.toJSDate();\n\n\t\treturn value;\n\t } else if (_.isObject(value, { zone: 'utc' })) {\n\t\treturn DateTime.fromObject(value, { zone: 'utc' }).toJSDate();\n\t } else {\n\t\treturn value;\n\t }\n\t}\n },\n class_methods: {\n },\n extensions: [ ]\n});\n\n/**\n * @ngdoc service\n * @name FlModelCache\n * @module fl.model_factory\n * @description\n * A service that manages a cache of model instances.\n * This cache is global across the application.\n */\n\nlet FlModelCache = (function() {\n function _type(h) {\n\tlet s = (_.isString(h)) ? h : ((_.isString(h.virtual_type)) ? h.virtual_type : h.type);\n\treturn (_.isNil(s)) ? null : s.replace(/::/g, '');\n };\n\n function _id(h) {\n\tif (h.hasOwnProperty('fingerprint'))\n\t{\n\t return _.split(h.fingerprint, '/')[1];\n\t}\n\telse if (h.hasOwnProperty('id'))\n\t{\n\t return h.id;\n\t}\n\telse if (h.type == 'Paperclip::Attachment')\n\t{\n\t if (h.hasOwnProperty('urls'))\n\t {\n\t\treturn h.urls.original;\n\t }\n\t else\n\t {\n\t\treturn h.original;\n\t }\n\t}\n\telse\n\t{\n\t return undefined;\n\t}\n };\n\n function _cache_id(h) {\n\tlet id = _id(h);\n\treturn (id == undefined) ? undefined : (_type(h) + '/' + id);\n };\n\n function FlModelCache() {\n\tthis._model_cache = new jscache();\n };\n FlModelCache.prototype.constructor = FlModelCache;\n \n /**\n * @ngdoc method\n * @name FlModelCache#get\n * @description\n * Gets a model instance from the cache, if one is present.\n * @param {Object} h An object containing the model's description. The factory\n * typically expects two properties, *type* and *id*, as described below.\n * However, it can also handle Paperclip attachments, which don't have an *id*\n * property since they don't really live in the database (Paperclip attachments are\n * manufactured on the fly from specialized attributes in a Rails model): in that\n * case, the identifier is the URL of the original file representation.\n * \n * @property {String} h.type A string containing the Rails name of the model class,\n * for example *Fl::Core::User*.\n * @property h.id An integer or string value containing the object identifier in the\n * database.\n * @property {Object} h.urls If this is a Paperclip attachment, this is an object containing\n * the attachment's URLs; the identifier is the value of the *original* property.\n * \n * @return Returns an instance of a model service, if one is present in the cache.\n */\n\n FlModelCache.prototype.get = function(h) {\n\tlet id = _cache_id(h);\n\treturn (id == undefined) ? null : this._model_cache.get(id);\n };\n\n /**\n * @ngdoc method\n * @name FlModelCache# put\n * @description\n * Puts a model instance in the cache.\n * \n * @param o The model instance to place in the cache.\n */\n\n FlModelCache.prototype.put = function(o) {\n\tlet id = _cache_id(o);\n\tif (id != undefined) this._model_cache.set(id, o);\n };\n\n /**\n * @ngdoc method\n * @name FlModelCache#remove\n * @description\n * Removes a model instance from the cache.\n * \n * @param o The model instance to remove from the cache.\n */\n\n FlModelCache.prototype.remove = function(o) {\n\tlet id = _cache_id(o);\n\tif (id != undefined) this._model_cache.del(id);\n };\n\n /**\n * @ngdoc method\n * @name FlModelCache#clear\n * @description\n * Clears the cache.\n */\n\n FlModelCache.prototype.clear = function() {\n\tthis._model_cache.clear();\n };\n\n /**\n * @ngdoc method\n * @name FlModelCache#size\n * @description\n * Returns the number of cached records.\n *\n * @return Returns the number of objects in the cache.\n */\n\n FlModelCache.prototype.size = function() {\n\treturn this._model_cache.size();\n };\n\n return FlModelCache;\n})();\n\n/**\n * @ngdoc service\n * @name FlModelFactory\n * @module fl.model_factory\n * @description\n * A service that manages a registry of names of model services.\n *\n * For example, a module registers its known model services as follows:\n *
\n *    const { FlClassManager } = require('fl/framework/object_system');\n *    const { FlModelBase, FlGlobalModelFactory } = require('fl/framework/model_factory');\n *\n *    let MyModelOne = FlClassManager.make_class({\n *      name: 'MyModelOne',\n *      superclass: 'FlModelBase',\n *      ...\n *    });\n *\n *    let MyModelTwo = FlClassManager.make_class({\n *      name: 'MyModelTwo',\n *      superclass: 'FlModelBase',\n *      ...\n *    });\n *\n *    FlGlobalModelFactory.register('my_module_name', [\n *      { service: MyModelOne, class_name: 'My::Model::One' },\n *      { service: MyModelTwo, class_name: 'My::Other::Model' }\n *    ]);\n *  
\n */\n\nlet FlModelFactory = (function() {\n function _type(h) {\n\tlet s = (_.isString(h)) ? h : ((_.isString(h.virtual_type)) ? h.virtual_type : h.type);\n\treturn (_.isNil(s)) ? null : s.replace(/::/g, '');\n };\n\n function FlModelFactory() {\n\tthis._model_cache = new FlModelCache();\n\tthis._model_services = { };\n }\n FlModelFactory.prototype.constructor = FlModelFactory;\n\n /**\n * @ngdoc method\n * @name FlModelFactory#register\n * @description Register model factory services provided by a module.\n * \n * @param {String} module The module's name.\n * @param {Array} services Array of factory services provided by this module.\n * Each element is an object that contains two properties: **service** is the class object for\n * the model service, and **class_name** is the name of the (Rails) class associated with this model.\n * The value of **class_name** is used as the lookup key in the model service registry.\n */\n\n FlModelFactory.prototype.register = function(module, services) {\n\tlet self = this;\n\t\n\t_.forEach(services, function(srv, idx) {\n\t if (_.isNil(srv.class_name))\n\t {\n\t\tconsole.log(\"(FlModelFactory): missing service class name in '\" + module + \"'\");\n\t }\n\t else\n\t {\n\t\tlet name = _type(srv.class_name);\n\t\t\n\t\tif (_.isNil(srv.service))\n\t\t{\n\t\t console.log(\"(FlModelFactory): missing service object in (\" + module + \")'\"\n\t\t\t\t+ srv.class_name + \"'\");\n\t\t}\n\t\telse\n\t\t{\n\t\t if (_.isObject(self._model_services[name])\n\t\t\t&& (self._model_services[name].module != module))\n\t\t {\n\t\t\tconsole.log(\"(FlModelFactory): service (\" + module + \")'\"\n\t\t\t\t + srv.class_name + \"' is already registered in module '\"\n\t\t\t\t + self._model_services[name].module + \"' and will overwrite it\");\n\t\t }\n\t\t\t\n\t\t self._model_services[name] = _.merge({ module: module }, srv);\n\t\t}\n\t }\n\t});\n };\n\n /**\n * @ngdoc method\n * @name FlModelFactory#unregister\n * @description Unregister the model factory services provided by a module.\n * This method is provided mostly to support testing.\n * \n * @param {String} module The module's name.\n */\n\n FlModelFactory.prototype.unregister = function(module) {\n\tlet name = _type(module);\n\n\tif (!_.isNil(this._model_services[name])) delete this._model_services[name];\n };\n \n /**\n * @ngdoc method\n * @name FlModelFactory#service_for\n * @description Gets a registered service.\n * \n * @param {String|Object} cname If the value is a string, it is the name of the data class\n * to look up. If it is an object, it is a representation of a model's data, and is expected to\n * have the property **type** (and optionally **virtual_type**), which contains the name of the data class.\n * If **virtual_type** is present, use that value for the name of the data class; otherwise, use **type**.\n * The virtual type is defined by some classes that want to use a generic type name instead of the\n * specific one; for example, a class that is stored via ActiveRecord and one stored in Neo4j may both\n * map to a generic one at the API level.\n *\n * @return {Object} Returns the service object that was registered under _cname_; if no service\n * object is registered under that name, returns `null`.\n */\n\n FlModelFactory.prototype.service_for = function(cname) {\n\tlet cn = _type(cname);\n\treturn (_.isObject(this._model_services[cn])) ? this._model_services[cn].service : null;\n };\n \n /**\n * @ngdoc method\n * @name FlModelFactory#services\n * @description Gets the registered services.\n * \n * @return {Object} Returns an object listing all registered model services; the properties\n * are data class names, and the values are objects containing the service description:\n * - **name** is the data class name.\n * - **service** is the service object.\n * - **module** is the name of the module that registered this service.\n */\n\n FlModelFactory.prototype.services = function() {\n\treturn this._model_services;\n };\n \n /**\n * @ngdoc method\n * @name FlModelFactory#cache\n * @description Gets the model cache used by the factory.\n * \n * @return {FlModelCache} Returns the instance of {@sref FlModelCache} used by the factory for\n * managing the model instances.\n */\n\n FlModelFactory.prototype.cache = function() {\n\treturn this._model_cache;\n };\n\n FlModelFactory.prototype._create_internal = function(h, null_on_failure) {\n\tlet o = this._model_cache.get(h);\n\tif (o)\n\t{\n\t o.refresh(h);\n\t}\n\telse\n\t{\n\t let srv = this.service_for(h);\n\t if (srv)\n\t {\n\t\to = new srv(h);\n\t\tthis._model_cache.put(o);\n\t }\n\t else\n\t {\n\t\to = (null_on_failure) ? null : h;\n\t }\n\t}\n\n\treturn o;\n };\n\n /**\n * @ngdoc method\n * @name FlModelFactory#create\n * @description Create an instance or an array of instances based on the hash\n * representation of objects. Objects already in the cache are refreshed with\n * the contents of the representation before they are returned.\n * \n * @param {Object|Array} obj_or_array The object containing a model instance's\n * properties, or and array of objects containing multiple model instances.\n * @param {Boolean} null_on_failure If the value is truthy, then if an instance cannot be built\n * the return value is `null`; otherwise, the original argument is returned.\n * The default is to return the original argument on failure, so that classes that convert properties\n * from a simple object to a class instance are still left with the simple object on conversion failure.\n * \n * @return If *obj_or_array* is an object, returns the\n * corresponding model instance (or `null` if no instance could be built).\n * If an array, returns an array of model instances.\n */\n\n FlModelFactory.prototype.create = function(obj_or_array, null_on_failure) {\n\tif (obj_or_array)\n\t{\n\t if (_.isArray(obj_or_array))\n\t {\n\t\tlet self = this;\n\t\treturn _.map(obj_or_array, function(v, idx) {\n\t\t return self._create_internal(v, null_on_failure);\n\t\t});\n\t }\n\t else\n\t {\n\t\treturn this._create_internal(obj_or_array, null_on_failure);\n\t }\n\t}\n\telse\n\t{\n\t return null;\n\t}\n };\n\n return FlModelFactory;\n})();\n\n/**\n * @ngdoc service\n * @name FlGlobalModelFactory\n * @module fl.model_factory\n * @description\n * The global model factory. This is an instance of {@sref FlModelFactory} that is globally accessible\n * and can be used as the applicationwide model factory.\n */\n\nconst FlGlobalModelFactory = new FlModelFactory();\n\nlet _default_factory = FlGlobalModelFactory;\n\n/**\n * @ngdoc method\n * @name FlModelFactory#create\n * @classmethod\n * @description Return the default model factory instance.\n * The initial value is {@sref FlGlobalModelFactory}.\n * \n * @return Returns the instance of {@sref FlModelFactory} to use for creating model instances.\n */\n\nFlModelFactory.defaultFactory = function() {\n return _default_factory;\n};\n\nmodule.exports = { FlModelBase, FlModelCache, FlModelFactory, FlGlobalModelFactory };\n","const _ = require('lodash');\n\n/**\n * @ngdoc module\n * @name fl.object_system\n * @module fl\n * @description\n * The Fl object system manages class definitions and object instantiation.\n */\n\n/**\n * @ngdoc service\n * @name FlExtensions\n * @module fl.object_system\n * @description\n * A service to provide class extension functionality.\n * A class extension is an object that contains information about how to extend the functionality of\n * another object (typically, a class).\n * \n * An extension has up to four components:\n * - *instance_methods* are functions to be installed in the object's prototype, if one is present.\n * - *class_methods* are functions to be installed in the object itself.\n * - *methods* acts as an alias for *instance_methods*, and also is used to provide dynamic method\n * definitions, as described in {@sref FlExtensions#register}.\n * - the *initializer* is a function called during object construction, and used to initialize\n * properties related to the extension.\n *\n * All properties are optional, although an extension that defines none is obviously not very useful.\n * \n * The *methods* component can be implemented as either an object (hash), or as a function; the extension\n * utilities install it differently, depending on its type; see {@sref FlExtensions#register}.\n * The *class_methods* and *instance_methods* components are always objects.\n *\n * For example, this extension defines a method `_append` that appends two values to a common prefix,\n * and an initializer that load the value of the prefix in the `_$scope` property.\n * (It assumes that `this` has defined a `_$cope` property.)\n * ```\n * let MyExtension = FlExtensions.named('MyExtension', {\n * methods: {\n * _append: function(one, two) {\n * returns this._$scope._prefix + one + ':' + two;\n * }\n * },\n * initializer: function(pass) {\n * if (pass == 'post')\n * {\n * this._$scope._prefix = 'my prefix: ';\n * }\n * }\n * });\n * ```\n */\n\nlet FlExtensions = { };\n\nFlExtensions._named_registry = { };\nFlExtensions.AlreadyRegistered = function AlreadyRegistered(message) {\n this.message = message;\n this.name = 'AlreadyRegistered';\n};\nFlExtensions.AlreadyRegistered.prototype.constructor = FlExtensions.AlreadyRegistered;\n\nFlExtensions.NotRegistered = function NotRegistered(message) {\n this.message = message;\n this.name = 'NotRegistered';\n};\nFlExtensions.NotRegistered.prototype.constructor = FlExtensions.NotRegistered;\n\n/**\n * @ngdoc method\n * @name FlExtensions#named\n * @classmethod\n * @module fl.object_system\n * @description\n * Create a named extension, which clients can then find by name.\n * \n * @param {string} name The extension name.\n * @param {object} ext The extension.\n * @param {boolean} overwrite If `true` and an extension by this name is already registered, overwrite\n * the current value. Otherwise, throw an exception.\n * \n * @return {object} Returns _ext_.\n * \n * @throws Throws an exception if _name_ is already registered.\n */\n\nFlExtensions.named = function(name, ext, overwrite) {\n let xo = FlExtensions._named_registry[name];\n if (_.isObject(xo))\n {\n\tif (overwrite === true)\n\t{\n\t xo.extension = ext;\n\t}\n\telse\n\t{\n\t throw new FlExtensions.AlreadyRegistered('extension :' + name + ' is already registered');\n\t}\n }\n else\n {\n\tFlExtensions._named_registry[name] = { name: name, extension: ext };\n }\n\n return ext;\n};\n\n/**\n * @ngdoc method\n * @name FlExtensions#list\n * @classmethod\n * @module fl.object_system\n * @description\n * List the registered extensions.\n * \n * @param {boolean} full If `true`, the element in the returned array are objects containing two\n * property: *name* is the extension name, and *extension* the extension object. Otherwise,\n * the returned array contains just the registered names for the extensions.\n *\n * @return {array} Returns an array containing all registered extensions.\n */\n\nFlExtensions.list = function(full) {\n let xf = (full === true) ? true : false;\n \n return _.reduce(FlExtensions._named_registry, function(acc, ev, ek) {\n\tacc.push((xf) ? ev : ek);\n\treturn acc;\n }, [ ]);\n};\n\n/**\n * @ngdoc method\n * @name FlExtensions#lookup\n * @classmethod\n * @module fl.object_system\n * @description\n * Look up a named extension.\n * \n * @param {string|object} name The extension name or descriptor.\n * If the value is an object, it must contain one of the properties **methods** or **initializer**,\n * or both, and **methods** must be an object or a function and **initializer** a function.\n * In this case, the method returns _name_.\n * @param {boolean} raise Controls the behavior on a lookup failure.\n * \n * @return {object} Returns the extension. If _name_ is not the name of a registered extension, it\n * returns `undefined` if _raise_ is `false`, and throws an exception if _raise_ is any other value\n * (hence by default the function raises an exception).\n * \n * @throws Throws an exception if _name_ is not registered.\n */\n\nFlExtensions.lookup = function(name, raise) {\n if (_.isObject(name))\n {\n\tif (!(_.isObject(name.methods) || _.isFunction(name.methods)) && !_.isFunction(name.initializer))\n\t{\n\t throw new FlExtensions.NotRegistered('lookup of extension by object must include either :methods or :initializer');\n\t}\n\t\n\treturn name;\n }\n else\n {\n\tif (FlExtensions._named_registry[name]) return FlExtensions._named_registry[name].extension;\n }\n \n if (raise === false) return undefined;\n\n throw new FlExtensions.NotRegistered('extension :' + name + ' is not registered');\n};\n\n/**\n * @ngdoc method\n * @name FlExtensions#register\n * @classmethod\n * @module fl.object_system\n * @description\n * Register the method components of an extension with an object.\n * \n * If _ex_**.class_methods** is present, the function iterates over all properties defined in\n * _ex_**.class_methods**, and assigns their value to a property by the same name in _obj_.\n * \n * If _ex_**.instance_methods** is present, the function iterates over all properties defined in\n * _ex_**.instance_methods**, and assigns their value to a property by the same name in _obj_'s prototpye\n * (if one is defined).\n * \n * If _ex_**.methods** is an object, it behaves as for the _ex_.**instance_methods** property; in other\n * words, it acts as an alias for _ex_.**instance_methods**.\n * \n * If _ex_**.methods** is a function, it calls it using _obj_ as the **this** for the call; the assumption is\n * that the extension function then proceeds to define properties in _obj_ as needed. This makes it possible\n * to set methods in _obj_ dynamically.\n * \n * @param {Object|String} ex The extension to add to _obj_; if passed as a string, the value is looked up\n * in the extensions registry.\n * @param {Object} obj The object to extend with the contents of _ex_**.methods**.\n *\n * @return {Object} Returns _obj_.\n */\n\nFlExtensions.register = function(ex, obj) {\n ex = FlExtensions.lookup(ex, false);\n\n if (!_.isNil(obj) && !_.isNil(ex))\n {\n\tlet proto = obj.prototype;\n\n\tif (_.isObject(ex.class_methods))\n\t{\n\t _.forEach(ex.class_methods, function(mv, mk) {\n\t\tobj[mk] = mv;\n\t });\n\t}\n\n\tif (_.isObject(ex.instance_methods) && !_.isUndefined(proto))\n\t{\n\t _.forEach(ex.instance_methods, function(mv, mk) {\n\t\tproto[mk] = mv;\n\t });\n\t}\n\t\n\tif (_.isFunction(ex.methods))\n\t{\n\t ex.methods.call(obj);\n\t}\n\telse if (_.isObject(ex.methods) && !_.isUndefined(proto))\n\t{\n\t _.forEach(ex.methods, function(mv, mk) {\n\t\tproto[mk] = mv;\n\t });\n\t}\n }\n\n return obj;\n};\n\n/**\n * @ngdoc method\n * @name FlExtensions#initialize\n * @classmethod\n * @module fl.object_system\n * @description\n * Call the extension initializer on an object.\n * \n * If _ex_**.initializer** is a function, it calls it using _obj_ as the **this** for the call; the assumption\n * is that the extension function then proceeds to modify the state of _obj_ as needed.\n * \n * @param {Object} ex The extension to initialize in _obj_; if passed as a string, the value is looked up\n * in the extension registry.\n * @param {Object} obj The object to extend by _ex_**.initializer**; this is typically an object or a function.\n * @param {String} pass The initialization pass:\n * - **pre** The initializer is being called before the object state is constructed: this is used to set up\n * state that the object's initializer may need.\n * - **post** The initializer is being called after the object state is constructed.\n * The value of _pass_ is passed to the initializer.\n *\n * @return {Object} Returns _obj_.\n */\n\nFlExtensions.initialize = function(ex, obj, pass) {\n ex = FlExtensions.lookup(ex, false);\n if (!_.isNil(obj) && !_.isNil(ex) && _.isFunction(ex.initializer))\n {\n\tex.initializer.call(obj, pass);\n }\n\n return obj;\n};\n\n/**\n * @ngdoc type\n * @name FlRoot\n * @module fl.object_system\n * @description\n * The root class for all Fl classes.\n *\n * This is the root of the Fl class hierarchy; {@sref FlClassManager#make_class} uses it as the\n * superclass if one is not defined in the options.\n *\n * Note that FlRoot is a ECMAScript 2015 (and later) class.\n * \n * @class FlRoot\n */\n\nconst FlRoot = class FlRoot {\n constructor() {\n\tthis.__extensions = [ ];\n }\n};\n\nFlRoot.__name = 'FlRoot';\nFlRoot.__superclass = null;\nFlRoot.__extensions = [ ];\nFlRoot.prototype.initialize = function() { };\n\n/**\n * @ngdoc method\n * @name FlRoot#__init_extensions\n * @module fl.object_system\n * @description\n * Load the **initializer** component of a set of extensions.\n *\n * If _ext_ is an object, it iterates over all its elements and registers each\n * extension's **initializer** component with **this**, using {@sref FlExtensions#initialize}.\n * This initializes all the listed extension properties in the object.\n * \n * The class builder {@sref FlClassManager#make_class} automatically generates a call to this method\n * in each class initializer, passing the extensions in the class options' **extensions** property.\n * \n * @param {Array} ext An array containing the extension descriptors.\n * @param {String} pass The initialization pass; see {@sref FlExtensions#initialize}.\n */\n\nFlRoot.prototype.__init_extensions = function(ext, pass) {\n let self = this;\n _.forEach(ext, function(ev, eidx) {\n\tFlExtensions.initialize(ev, self, pass);\n });\n};\n\nFlRoot.UndefinedSuper = function UndefinedSuper(message) {\n this.message = message;\n this.name = 'UndefinedSuper';\n};\nFlRoot.UndefinedSuper.prototype.constructor = FlRoot.UndefinedSuper;\n\n/**\n * @ngdoc method\n * @name FlRoot#__super_init\n * @module fl.object_system\n * @description\n * Calls the initializer for the superclass.\n *\n * This method looks up the class in *name*, which should be the superclass, and then calls its\n * **initialize** method, passing all the remaining arguments. The **initialize** method is bound\n * to the **this** value.\n * \n * @param {String|Function} name The name of the superclass, or the superclass constructor.\n * If not provided, use {@sref FlRoot}.\n */\n\nFlRoot.prototype.__super_init = function(name) {\n let args = Array.from(arguments);\n args.shift();\n args.unshift('initialize');\n args.unshift(name);\n return this.__super.apply(this, args);\n};\n\n/**\n * @ngdoc method\n * @name FlRoot#__super\n * @module fl.object_system\n * @description\n * Calls the superclass implementation of a method.\n *\n * This method looks up the class in *sc*, which should be the superclass, then looks up the method\n * *name* in its prototype, which it then calls, passing all the remaining arguments.\n * The called method is bound to the **this** value.\n *\n * @param {String|Function} sc The name of the superclass, or the superclass constructor.\n * If `null` or `undefined`, use {@sref FlRoot}.\n * @param {String} name The name of the method to call.\n */\n\nFlRoot.prototype.__super = function(sc, name) {\n if (_.isNil(sc)) sc = FlRoot;\n let cl = FlClassManager.get_class(sc);\n if (!_.isFunction(cl)) throw new FlClassManager.MissingClass(`superclass '${sc}' is not registered`);\n if (!_.isFunction(cl.prototype[name])) throw new FlRoot.UndefinedSuper(`superclass ${cl.__name} does not implement method '${name}'`);\n \n let args = Array.from(arguments);\n return cl.prototype[name].apply(this, args.slice(2));\n};\n\n/**\n * @ngdoc service\n * @name FlClassManager\n * @module fl.object_system\n * @description\n * A service to manage class hierarchies and create class instances.\n */\n\nconst FlClassManager = {\n _class_registry: {\n\t'FlRoot': FlRoot\n }\n};\n\nFlClassManager.MissingClass = function MissingClass(message) {\n this.message = message;\n this.name = 'MissingClass';\n};\nFlClassManager.MissingClass.prototype.constructor = FlClassManager.MissingClass;\n\nFlClassManager.AlreadyDefinedClass = function AlreadyDefinedClass(message) {\n this.message = message;\n this.name = 'AlreadyDefinedClass';\n};\nFlClassManager.AlreadyDefinedClass.prototype.constructor = FlClassManager.AlreadyDefinedClass;\n\nFlClassManager.NotAClass = function NotAClass(message) {\n this.message = message;\n this.name = 'NotAClass';\n};\nFlClassManager.NotAClass.prototype.constructor = FlClassManager.NotAClass;\n\nFlClassManager.AlreadyDefinedClass = function AlreadyDefinedClass(message) {\n this.message = message;\n this.name = 'AlreadyDefinedClass';\n};\nFlClassManager.AlreadyDefinedClass.prototype.constructor = FlClassManager.AlreadyDefinedClass;\n\n/**\n * @ngdoc method\n * @name FlClassManager#make_class\n * @classmethod\n * @module fl.object_system\n * @description\n * Build an ECMAScript 2015 class.\n *\n * The class is built as follows:\n * 1. If **opts.superclass** is not present, or if it does not resolve to a function, set the superclass\n * to {@sref FlRoot}.\n * 2. Define a ECMASCRIPT 2015 class with a constructor and the `__super` method.\n * 3. The constructor first calls `super` with no arguments, and then calls an initializer\n * wrapper generated as follows:\n * - If **opts.initializer** is not defined, an initializer is generated that calls the superclass\n * initializer. Note that, if an initializer is provided,\n * it should make a call to `__super_init` in order to initialize the superclass; in this case,\n * the argument list for the `__super_init` method is defined by the initializer code.\n * - The initializer is wrapped by a function that performs the following steps:\n * 1. Initializes the registered extensions from **opts.extensions**, setting the pass name to `pre`.\n * 2. Calls the initializer from the previous step.\n * 3. Initializes the registered extensions from **opts.extensions**, setting the pass name to `post`.\n * 4. A number of properties are set in the class:\n * - **__name** contains the class name.\n * - **__extensions** is an array of all registered extensions, including those that were registered\n * in the superclasses.\n * - **__superclass** is the superclass constructor.\n * - **initialize** is the value of **opts.initializer** (or the generated function if\n * **opts.initializer** was not defined).\n * 5. A number of properties are set in the class prototype, and are therefore inherited by class instances:\n * - **__class** is the class constructor.\n * - **__superclass** is the superclass constructor; note that this could also be obtained from\n * **__class**.\n * 6. A default **factory** class method is defined that creates an instance object. This method takes the\n * same parameters as the constructor, and is defined early enough that it can be overridden by a\n * **factory** method defined in **class_methods**.\n * 8. Iterate over all elements of **opts.extensions** register each extension with the class,\n * using {@sref FlExtensions#register}. \n * 9. If **opts.instance_methods** is an object, copy all its key/value pairs to the prototype;\n * this registers additional instance methods.\n * 10. If **opts.class_methods** is an object, copy all its key/value pairs to the constructor;\n * this registers additional class (static) methods.\n * 11. If **opts.class_properties** is an object, register all its key/value pairs as properties in the\n * constructor.\n * 12. If **opts.instance_properties** is an object, register all its key/value pairs as properties in the\n * prototype.\n * 13. Register the class under the given class name; {@sref FlClassManager#get_class} can be used\n * to fetch class constructors by name, and {@sref FlClassManager#instance_factory} to create\n * instances of a given class.\n * \n * Note that the order in which actions are performed implies that instance methods by the same name as those\n * loaded in the extensions will override the extension implementations.\n *\n * ##### The **__super** and **__super_init** methods\n *\n * JavaScript classes use the `super` keyword to instruct the code to look up a method in the class\n * inheritance chain. For example:\n * ```\n * class Sub extends Base {\n * constructor() { super(); }\n * my_method(arg) {\n * super.my_method(arg);\n * do_my_work(arg);\n * }\n * };\n * ```\n * Unfortunately, `super` is available only in methods defined in the class body, so that instance methods\n * in **opts.instance_methods** won't be able to call the superclass implementation.\n * {@sref FlRoot} defines the {@sref FlRoot#__super} method that provides equivalent functionality,\n * at the cost of some ugliness.\n * The arguments for {@sref FlRoot#__super} are the superclass name and the method name, followed by\n * arguments to the method itself; therefore, the equivalent usage of {@sref FlRoot#__super} is as follows:\n * ```\n * let Sub = FlClassManager.make_class({\n * name: 'Sub',\n * superclass: 'Base',\n * instance_methods: {\n * my_method: function(arg) {\n * this.__super('Base', 'my_method', arg);\n * do_my_work(arg);\n * }\n * }\n * });\n * ```\n * Not the prettiest, but it works.\n * Note that there is no requirement to make the `__super` call.\n * If you don't call the `__super` method, you completely override the superclass implementation;\n * if you do call it, you extend it instead.\n *\n * Initializers have a similar problem, since they need to call the superclass initializer.\n * {@sref FlRoot} defines the instance method {@sref FlRoot#__super_init} that calls\n * the superclass initializer bound to `this`. For example:\n * ```\n * let Base = FlClassManager.make_class({\n * name: 'Base',\n * initializer: function(a1) {\n * this.__super_init();\n * this._a1 = a1;\n * }\n * });\n *\n * let Sub = FlClassMagaer.make_class({\n * name: 'Sub',\n * superclass: Base,\n * initializer: function(a1, a2) {\n * this.__super_init('Base', a1);\n * this._a2 = a2;\n * }\n * });\n *\n * let s = new Sub('A1', 'A2');\n * console.log(s);\n * ```\n * It this code is executed, the console will show:\n * ```\n * Sub { __extensions: [], _a1: 'A1', _a2: 'A2' }\n * ```\n * If subclasses don't define an initializer, {@sref FlClassManager#make_class} generates one that\n * makes a call to {@sref FlRoot#__super_init} using all the arguments passed to the constructor; this way,\n * class definitions in the chain can leave the initializer undefined, and the objects will still\n * be initialized properly. The test case contain an example of this behavior.\n *\n * ##### Sample usage\n *\n * Given the following class defintions:\n * ```\n * let SuperTestBase = FlClassManager.make_class({\n * name: 'SuperTestBase',\n * initializer: function(m) {\n * console.log(\"SuperTestBase init IN\");\n * this.__super_init();\n * this._m = m;\n * console.log(\"SuperTestBase init OUT\");\n * },\n * instance_methods: {\n * my_method: function(msg) {\n * console.log(\"---------- SuperTestBase.my_method IN\");\n * \t console.log(\"SuperTestBase : \" + msg + ' - ' + this._m);\n * \t console.log(\"---------- SuperTestBase.my_method OUT\");\n * }\n * }\n * });\n * \n * let SuperTestBase2 = FlClassManager.make_class({\n * name: 'SuperTestBase2',\n * instance_methods: {\n * my_method: function(msg) {\n * console.log(\"---------- SuperTestBase2.my_method IN\");\n * console.log(\"SuperTestBase2 : \" + msg);\n * console.log(\"---------- SuperTestBase2.my_method OUT\");\n * }\n * }\n * });\n * \n * let SuperTestSub = FlClassManager.make_class({\n * name: 'SuperTestSub',\n * superclass: SuperTestBase,\n * initializer: function(m) {\n * console.log(\"SuperTestSub init IN\");\n * this.__super_init('SuperTestBase', m);\n * console.log(\"SuperTestSub init OUT\");\n * },\n * instance_methods: {\n * my_method: function(msg) {\n * console.log(\"---------- SuperTestSub.my_method IN\");\n * console.log(\"SuperTestSub: \" + msg + ' - ' + this._m);\n * this.__super('SuperTestBase', 'my_method', msg);\n * console.log(\"---------- SuperTestSub.my_method OUT\");\n * }\n * }\n * });\n * \n * let SuperTestSub2 = FlClassManager.make_class({\n * name: 'SuperTestSub',\n * superclass: SuperTestBase2,\n * instance_methods: {\n * my_method: function(msg) {\n * console.log(\"---------- SuperTestSub2.my_method IN\");\n * console.log(\"SuperTestSub2: \" + msg);\n * this.__super('SuperTestBase2', 'my_method', msg);\n * console.log(\"---------- SuperTestSub2.my_method OUT\");\n * }\n * }\n * });\n * \n * let SuperTestSubSub = FlClassManager.make_class({\n * name: 'SuperTestSubSub',\n * superclass: SuperTestSub,\n * initializer: function(m) {\n * console.log(\"SuperTestSubSub init IN\");\n * this.__super_init('SuperTestSub', m*2);\n * console.log(\"SuperTestSubSub init OUT\");\n * },\n * instance_methods: {\n * my_method: function(msg) {\n * console.log(\"---------- SuperTestSubSub.my_method IN\");\n * console.log(\"SuperTestSubSub: \" + msg + ' - ' + this._m);\n * this.__super('SuperTestSub', 'my_method', '(' + msg + ')');\n * console.log(\"---------- SuperTestSubSub.my_method OUT\");\n * }\n * }\n * });\n * ```\n * Here is a log from a Node console session:\n * ```\n * > sub = new SuperTestSub(10);\n * SuperTestSub init IN\n * SuperTestBase init IN\n * SuperTestBase init OUT\n * SuperTestSub init OUT\n * SuperTestSub init IN\n * SuperTestBase init IN\n * SuperTestBase init OUT\n * SuperTestSub init OUT\n * SuperTestSub { __extensions: [], _m: 10 }\n * > sub.my_method('sub');\n * ---------- SuperTestSub.my_method IN\n * SuperTestSub: sub - 10\n * ---------- SuperTestBase.my_method IN\n * SuperTestBase : sub - 10\n * ---------- SuperTestBase.my_method OUT\n * ---------- SuperTestSub.my_method OUT\n * undefined\n * >\n * ```\n * ```\n * > subsub = new SuperTestSubSub(15);\n * SuperTestSubSub init IN\n * SuperTestSub init IN\n * SuperTestBase init IN\n * SuperTestBase init OUT\n * SuperTestSub init OUT\n * SuperTestSubSub init OUT\n * SuperTestSubSub init IN\n * SuperTestSub init IN\n * SuperTestBase init IN\n * SuperTestBase init OUT\n * SuperTestSub init OUT\n * SuperTestSubSub init OUT\n * SuperTestSubSub init IN\n * SuperTestSub init IN\n * SuperTestBase init IN\n * SuperTestBase init OUT\n * SuperTestSub init OUT\n * SuperTestSubSub init OUT\n * SuperTestSubSub { __extensions: [], _m: 30 }\n * > subsub.my_method('subsub');\n * ---------- SuperTestSubSub.my_method IN\n * SuperTestSubSub: subsub - 30\n * ---------- SuperTestSub.my_method IN\n * SuperTestSub: (subsub) - 30\n * ---------- SuperTestBase.my_method IN\n * SuperTestBase : (subsub) - 30\n * ---------- SuperTestBase.my_method OUT\n * ---------- SuperTestSub.my_method OUT\n * ---------- SuperTestSubSub.my_method OUT\n * undefined\n * > \n * ```\n * ```\n * > sub2 = new SuperTestSub2(20);\n * SuperTestSub2 { __extensions: [] }\n * > sub2.my_method('sub2');\n * ---------- SuperTestSub2.my_method IN\n * SuperTestSub2: sub2\n * ---------- SuperTestBase2.my_method IN\n * SuperTestBase2 : sub2\n * ---------- SuperTestBase2.my_method OUT\n * ---------- SuperTestSub2.my_method OUT\n * undefined\n * > \n * ```\n *\n * @param {Object} opts A hash containing the class description.\n * @property {String} opts.name The class name; this is the also the name under which the class constructor\n * is registered.\n * @property {Function|String} opts.superclass If the class inherits form a superclass, this is the superclass\n * constructor, or a the name of the superclass.\n * If this property is not given, the class will inherit from {@sref FlRoot}.\n * @property {Function} opts.initializer The function called by the constructor to initialize the object.\n * It should include a call to **__super_init**.\n * If the option is not present, an initializer is generated as described above..\n * @property {Object} opts.instance_methods A hash containing the instance methods for the class.\n * The values for the object's properties are functions; the contents of the hash are placed in the\n * constructor's prototype.\n * @property {Object} opts.class_methods A hash containing the class methods for the class.\n * The values for the object's properties are functions; the contents of the hash are placed in the\n * constructor.\n * @property {Object} opts.class_properties A hash containing the class properties for the class.\n * Each key/value pair is registered as a property in the constructor.\n * The keys are property names, and the values are objects containing the property descriptor.\n * @property {Object} opts.instance_properties A hash containing the instance properties for the class.\n * Each key/value pair is registered as a property in the prototype.\n * The keys are property names, and the values are objects containing the property descriptor.\n * @property {Array} opts.extensions An array containing the list of extensions for the class. The elements\n * are the names of registered extensions. See {@sref FlExtensions}.\n * \n * @return {Function} Returns the value of the constructor that was created.\n *\n * @throws Throws an exception if _name_ is already registered.\n */\n\nFlClassManager.make_class = function(opts) {\n let cname = opts.name;\n if (_.isNil(cname)) throw new FlClassManager.MissingClass('missing :name property');\n if (!_.isNil(FlClassManager.get_class(cname))) throw new FlClassManager.AlreadyDefinedClass(`class already defined: ${cname}`);\n \n // If no superclass is defined, we extend the root class\n // And, we trigger an exception if the superclass is given, but not registered\n\n let sname = (_.isNil(opts.superclass)) ? 'FlRoot' : opts.superclass;\n let superclass = FlClassManager.get_class(sname);\n if (!_.isFunction(superclass))\n {\n\tthrow new FlClassManager.MissingClass('superclass not found: ' + sname);\n }\n sname = superclass.__name;\n\n let extensions = [ ];\n if (_.isObject(opts.extensions))\n {\n\textensions = _.reduce(opts.extensions, function(acc, ev, eidx) {\n\t acc.push(FlExtensions.lookup(ev));\n\t return acc;\n\t}, [ ]);\n }\n\n // this eval initializes the ctor variable with the class constructor\n // Under some conditions, for mysterious reasons, if the constructor has no declared arguments\n // then no arguments are passed to it, and all hell breaks loose (well actually just the instances\n // are not initialized properly). Declaring a dummy argument fixes it; this 100% unadulterated\n // voodoo programming.\n \n let ctor = null;\n eval(`ctor = (function(_sc) {\n return class ${cname} extends _sc {\n constructor(dummy) {\n\t super(dummy);\n\t this.__initialize.apply(this, Array.from(arguments));\n }\n\n // __super() {\n\t// let args = Array.from(arguments);\n\t// let m = args[0];\n\t// return super[m].apply(this, args.slice(1));\n // }\n };\n })(superclass);`);\n\n ctor.__name = cname;\n ctor.__extensions = _.reduce(extensions, function(acc, ev, eidx) {\n\tacc.push(ev);\n\treturn acc;\n }, superclass.__extensions);\n ctor.__superclass = superclass;\n ctor.prototype.__class = ctor;\n ctor.prototype.__superclass = superclass;\n\n let init = opts.initializer;\n if (!_.isFunction(init)) eval(`init = function() {\n let args = Array.from(arguments);\n args.unshift('${sname}');\n this.__super_init.apply(this, args);\n };`);\n ctor.prototype.initialize = init;\n ctor.prototype.__initialize = (function(_extensions, _init) {\n\treturn function() {\n\t let args = Array.from(arguments);\n\n\t this.__init_extensions(_extensions, 'pre');\n\t _init.apply(this, Array.from(arguments));\n\t this.__init_extensions(_extensions, 'post');\n\t};\n })(ctor.__extensions, init);\n\n // the factory method is defined before we load the class methods to give clients a chance to\n // override it\n\n let args = [ ];\n let iarg;\n for (iarg=1 ; iarg <= init.length ; iarg++)\n {\n\targs.push('arg' + iarg);\n }\n\n ctor.factory = (function(_opts, _ctor) {\n\tfunction __factory(args) {\n\t return _ctor.apply(this, args);\n\t}\n\t__factory.prototype = Object.create(_ctor.prototype);\n\n\treturn function() {\n\t return new __factory(Array.from(arguments));\n\t};\n })(opts, ctor);\n\n _.forEach(extensions, function(ev, ek) { FlExtensions.register(ev, ctor); });\n\n if (_.isObject(opts.instance_methods))\n {\n\t_.forEach(opts.instance_methods, function(mv, mk) {\n\t ctor.prototype[mk] = mv;\n\t ctor.prototype[mk].__superclass = superclass;\n\t ctor.prototype[mk].__name = mk;\n\t});\n }\n\n if (_.isObject(opts.class_methods))\n {\n\t_.forEach(opts.class_methods, function(mv, mk) {\n\t ctor[mk] = mv;\n\t});\n }\n\n if (_.isObject(opts.class_properties))\n {\n\t_.forEach(opts.class_properties, function(mv, mk) {\n\t Object.defineProperty(ctor, mk, mv);\n\t});\n }\n\n if (_.isObject(opts.instance_properties))\n {\n\t_.forEach(opts.instance_properties, function(mv, mk) {\n\t Object.defineProperty(ctor.prototype, mk, mv);\n\t});\n }\n \n FlClassManager._class_registry[cname] = ctor;\n\n return ctor;\n};\n\n/**\n * @ngdoc method\n * @name FlClassManager#register_class\n * @classmethod\n * @module fl.object_system\n * @description\n * Register a class constructor.\n * \n * @param {Function} ctor The class constructor.\n * @param {String} name The name under which to register the class; if not given, uses the **name**\n * property of *ctor*.\n *\n * @return {Function} Returns _ctor_.\n * \n * @throws Throws an exception if:\n *\n * - _name_ is not defined, and _ctor_ does not have a **name** or **__name** property.\n * - _ctor_ is not a function.\n * - a class is already registered by the given name.\n */\n\nFlClassManager.register_class = function(ctor, name) {\n if (!_.isFunction(ctor)) throw new FlClassManager.NotAClass('you must register a function');\n if (!_.isString(name)) name = (_.isString(ctor.__name)) ? ctor.__name : ctor.name;\n if (!_.isString(name) || (name.length < 1)) throw new FlClassManager.NotAClass('missing class name to register');\n if (!_.isNil(FlClassManager.get_class(name))) throw new FlClassManager.AlreadyRegisteredClass(`class already registered: ${name}`);\n\n FlClassManager._class_registry[name] = ctor;\n\n return ctor;\n};\n\n/**\n * @ngdoc method\n * @name FlClassManager#get_class\n * @classmethod\n * @module fl.object_system\n * @description\n * Get a registered class constructor.\n * \n * @param {String|Function} name The name of the class to look up; as a convenience, if the value is a\n * function that looks like a class created by {@sref FlClassManager#make_class}, it is returned as-is.\n * \n * @return {Function|undefined} Returns the constructor registered under _name_ if one is available;\n * otherwise, returns **undefined**.\n */\n\nFlClassManager.get_class = function(name) {\n if (_.isString(name)) return FlClassManager._class_registry[name];\n if (_.isFunction(name) && _.isString(name.name) && (name.name.length > 0)) return name;\n\n return undefined;\n};\n\n/**\n * @ngdoc method\n * @name FlClassManager#instance_factory\n * @classmethod\n * @module fl.object_system\n * @description\n * Factory function for registered classes.\n *\n * This function calls {@sref FlClassManager#get_class} to obtain a constructor, and if one is found\n * it returns an instance of the class (using the **new** operator). Any arguments following _name_ \n * are passed to the constructor.\n * \n * @param {String|Function} name The name of the class to look up; as a convenience, you may pass a\n * class object as well.\n * \n * @return Returns an instance of the class registered under _name_ if one is available;\n * otherwise, returns **null**.\n */\n\nFlClassManager.instance_factory = function(name) {\n let ctor = FlClassManager.get_class(name);\n if (_.isFunction(ctor))\n {\n\tlet args = Array.from(arguments);\n\n\t// The first argument is the class name\n\n\targs.shift();\n\n\treturn ctor.factory.apply(ctor, args);\n }\n\n return null;\n};\n\n/**\n * @ngdoc method\n * @name FlClassManager#modelize\n * @classmethod\n * @module fl.object_system\n * @description\n * Modelize a hash.\n *\n * If _data_ is `null` or `undefined`, returns _data_.\n * If _data_ is an array, calls **map** on _data_, passing a function that calls the modelize function for\n * each element of the array (and therefore returns an array of modelized elements).\n * If _data_ is not an array, calls new ctor(data) to modelize the hash.\n * \n * The relevant part of the function consists of two steps:\n * 1. Resolve the constructor:\n *
ctor = FlClassManager.get_class(ctor);
\n * converts the *ctor* parameter into a constructor function.\n * 2. Instantiate the class:\n *
return new ctor(data);
\n * creates a new class instance.\n * \n * @param {String|Function} ctor The constructor function to use; if passed as a string, the value is\n * looked up in the class registry (using {@sref FlClassManager#get_class}).\n * @param {Object} data The object containing the hash to convert into a model object.\n */\n\nFlClassManager.modelize = function(ctor, data) {\n if (_.isNil(data)) return data;\n\n ctor = FlClassManager.get_class(ctor);\n if (_.isArray(data))\n {\n\treturn data.map(function(d) { return FlClassManager.modelize(ctor, d); });\n }\n else\n {\n\treturn new ctor(data);\n }\n};\n\nmodule.exports = { FlExtensions, FlClassManager };\n"],"names":["_","require","has_permission","FlExtensions","FlClassManager","FlModelBase","FlModelCache","FlModelFactory","FlGlobalModelFactory","ActiveStorageAttachment","ActiveStorageAttachedOne","ActiveStorageAttachedMany","NkpCoreUser","make_class","name","superclass","initializer","data","this","__super_init","instance_properties","instance_methods","refresh","__super","isObject","avatar","isUndefined","intro_json","_convert_JSON_value","current_sign_in_at","Date","has_role","role","r","toLowerCase","startsWith","substring","t","find","roles","e","idx","isString","class_properties","TYPE_NAME","get","class_methods","create","modelize","extensions","ROLE_USER","ROLE_SYSADMIN","ROLE_MODERATOR","ROLE_ANONYMOUS","ROLE_UNMONITORED","NkpCorePod","owner","defaultFactory","isArray","members","note_json","new_comment_count","p","permissions","NkpCorePodMember","actor","pod","map","reduce","acc","pv","pk","push","NkpCoreResourcePod","container","resource","resource_owner","resource_created_at","resource_updated_at","NkpCoreActorState","recent_checked_at","NkpCoreJoinInvitation","sent_by","accepted_by","isNil","emailed_at","expires_at","state_at","NkpCoreTrackingDirective","target","NkpCoreLinkedEntity","master","attachment","regions","LINK_TYPE_UPLOADED","LINK_TYPE_EXTERNAL","LINK_TYPE_REFERENCE","DATA_TYPE_IMAGE","DATA_TYPE_LINK","NkpCoreLinkedEntityRegion","linked_entity","author","geometry","JSON","parse","MODE_CONTRIBUTOR","MODE_FOLLOWER","MODE_BROADCAST","NkpCoreLinkedEntityShowcase","region","annotation","register","service","class_name","module","exports","FlAPIService","FlAPIServiceRegistry","FlGlobalAPIServiceRegistry","API_CFG","root_url_template","namespace","data_names","NkpCoreUserAPIService","srv_cfg","check_username","username","config","self","cfg","_make_config","params","_http_service","url_path_for","then","_response","check_email","email","change_password","user","current_password","new_password","confirm_password","password","password_confirmation","patch","_wrap_data","wrapped","Promise","resolve","_create_or_refresh_from_id","response_data","catch","reject","pods","to_hash","merge","verbosity","_make_index_config","_set_pagination_controls","modelFactory","response_error","topics","action","root_path","_expand_url_template","undefined","_id","REASONS","too_short","too_long","no_lowercase","no_uppercase","no_digit","no_symbol","is_password_valid","opts","min","max","rv","reasons","length","lc_count","uc_count","d_count","s_count","plen","c","charAt","is_valid","explicit_permissions","lcp","includes","grant_permission","pl","union","np","assign","revoke_permission","difference","variants","variant","style","ls","v","variant_url","url","attachments","set","a","axios","DEFAULT_SRV_CFG","xsrfCookieName","xsrfHeaderName","api_cfg","_api_cfg","_srv_cfg","getServiceConfig","_pg_names","pg_names","_showDidSucceed","pagination_controls","xsrfToken","token","response","error","_error","_pagination_controls","pg","initial_pagination_controls","_s","_p","setConfig","replace","getConfig","tid","post","process","put","delete","head","index","setShowDidSucceed","cb","id","__class","isFunction","show","_make_get_config","model","call","method","args","m","api_data","um","headers","_has_file_item","_add_content_type","flat","_flatten_data","_form_data","apply","update","destroy","response_status","cfgp","k","_pg","payload","forEach","extract_response_status","extract_response_error","ary","len","_status","tpl","fdx","rest","fragments","Array","indexOf","join","File","x","f","root","fk","fd","FormData","append","ct","has","unwrapped","setServiceConfig","s","status","rd","message","statusText","err","type","stack","details","split","isError","FlNestedAPIService","shallow_root_url_template","_services","services","sv","sk","_normalize_name","console","log","api_service","unregister","kk","service_info","n","info","srv","get_class","from","arguments","shift","jscache","DateTime","Error","fingerprint","updated_at","self_updated_at","isDate","getTime","_convert_value","created_at","op","value","av","aidx","ov","ok","_convert_date_value","l","fromISO","zone","isValid","toJSDate","fromRFC2822","fromHTTP","fromSQL","fromObject","_cache_id","h","hasOwnProperty","urls","original","virtual_type","_type","_model_cache","prototype","constructor","o","remove","del","clear","size","_model_services","service_for","cname","cn","cache","_create_internal","null_on_failure","obj_or_array","_default_factory","AlreadyRegistered","NotRegistered","named","ext","overwrite","xo","_named_registry","extension","list","full","xf","ev","ek","lookup","raise","methods","ex","obj","proto","mv","mk","initialize","pass","FlRoot","__extensions","__name","__superclass","__init_extensions","eidx","UndefinedSuper","unshift","sc","cl","MissingClass","slice","_class_registry","AlreadyDefinedClass","NotAClass","sname","ctor","eval","init","_extensions","_init","__initialize","iarg","factory","_opts","_ctor","__factory","Object","defineProperty","register_class","AlreadyRegisteredClass","instance_factory","d"],"sourceRoot":""}