{"id":19594728,"url":"https://github.com/michaeljymsgutierrez/arm-js-library","last_synced_at":"2025-07-17T07:34:59.360Z","repository":{"id":245233199,"uuid":"798142904","full_name":"michaeljymsgutierrez/arm-js-library","owner":"michaeljymsgutierrez","description":"ARM is a JavaScript library designed to manage API resources efficiently.","archived":false,"fork":false,"pushed_at":"2025-07-16T07:53:50.000Z","size":1866,"stargazers_count":4,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-17T04:52:24.342Z","etag":null,"topics":["centralized-data","crypto-js","hacktoberfest","help-wanted-documentations-demos","javascipt","json-api","lodash","mobx","reactjs","state-management","uuid"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/arm-js-library?activeTab=readme","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michaeljymsgutierrez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-05-09T07:15:20.000Z","updated_at":"2025-07-16T07:53:46.000Z","dependencies_parsed_at":"2024-07-15T18:26:15.418Z","dependency_job_id":"b6a5c901-1644-40c3-a330-9525e755541f","html_url":"https://github.com/michaeljymsgutierrez/arm-js-library","commit_stats":null,"previous_names":["michaeljymsgutierrez/arm-js-library"],"tags_count":50,"template":false,"template_full_name":null,"purl":"pkg:github/michaeljymsgutierrez/arm-js-library","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaeljymsgutierrez%2Farm-js-library","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaeljymsgutierrez%2Farm-js-library/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaeljymsgutierrez%2Farm-js-library/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaeljymsgutierrez%2Farm-js-library/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michaeljymsgutierrez","download_url":"https://codeload.github.com/michaeljymsgutierrez/arm-js-library/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaeljymsgutierrez%2Farm-js-library/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265577802,"owners_count":23791229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["centralized-data","crypto-js","hacktoberfest","help-wanted-documentations-demos","javascipt","json-api","lodash","mobx","reactjs","state-management","uuid"],"created_at":"2024-11-11T08:44:39.391Z","updated_at":"2025-07-17T07:34:59.352Z","avatar_url":"https://github.com/michaeljymsgutierrez.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\" style=\"margin-bottom:10px;\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/arm-js-library\"\u003e\n    \u003cimg src=\"https://assets-omega-neon.vercel.app/images/arm-js-title-logo.png\" alt=\"arm-js-logo\" height=\"200\" width=\"143.7\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/michaeljymsgutierrez/arm-js-library/actions/workflows/ci-cd.yml\"\u003e\n    \u003cimg src=\"https://github.com/michaeljymsgutierrez/arm-js-library/actions/workflows/ci-cd.yml/badge.svg\" alt=\"cicd-badge-logo\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/arm-js-library\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/npm_version-2.4.0-blue\" alt=\"npm-badge-logo\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/michaeljymsgutierrez/arm-js-library?tab=MIT-1-ov-file\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"license-badge-logo\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Table of Contents\n\n* [Overview](#overview)\n  * [Core Functionalities](#core-functionalities)\n  * [Key Features](#key-features)\n  * [Benefits](#benefits)\n* [Basic Usage](#basic-usage)\n* [Installation](#installation)\n* [Dependency Packages](#dependency-packages)\n  * [Initialization and Configuration](#initialization-and-configuration)\n    * [Initialization](#initialization)\n    * [Configuration](#configuration)\n* [Utilization](#utilization)\n  * [Request functions from server](#request-functions-from-server)\n    * [Passed Arguments: `Request functions from server`](#passed-arguments-request-functions-from-server)\n    * [Returned Object: `Request functions from server`](#returned-object-request-functions-from-server)\n  * [Retrieve functions from collections](#retrieve-functions-from-collections)\n  * [Create collection record function](#create-collection-record-function)\n  * [Remove collection record functions](#remove-collection-record-functions)\n  * [Push collection record function](#push-collection-record-function)\n* [Collection Records: `Properties and Functions`](#collection-records-properties-and-functions)\n* [Root Scope: `Functions`](#root-scope-functions)\n* [Utility Functions](#utility-functions)\n  * [Data Retrieval and Manipulation](#data-retrieval-and-manipulation)\n  * [Data Validation and Comparison](#data-validation-and-comparison)\n\n## Overview\n\n**ARM (API Resource Manager)** is a JavaScript library designed to centralize data management and simplify interactions with APIs. By providing a structured approach to handling and storing fetched data, ARM promotes efficient and flexible data usage throughout your application.\n\n### Core Functionalities\n* **Centralized Data Storage:** Organizes fetched data into easily accessible collections, acting as a single source of truth for your application's data.\n* **API Interactions:** Manages API requests and responses, providing methods for common HTTP operations (GET, POST, PUT, DELETE).\n* **Caching:** Optimizes performance by caching frequently accessed data, reducing API calls and improving response times.\n* **Request Management:** Tracks ongoing requests to prevent redundancy and manages their state.\n* **Utility Functions:** Offers helper functions for data manipulation, filtering, sorting, and other common operations.\n* **Root Scope:** An object that can be used to store and manage global state.\n\n### Key Features\n* **Collections:** Stores fetched data in collections for efficient retrieval and management.\n* **Record Management:** Provides methods to create, update, delete, and retrieve individual records within collections.\n* **Reactive Data:** Employs observable patterns (likely through a library like Mobx) to enable real-time updates and dependency tracking.\n* **Asynchronous Operations:** Handles API interactions asynchronously using Promises for non-blocking operations.\n* **Error Handling:** Manages errors gracefully and provides informative feedback.\n* **Configurability:** Allows customization of API endpoints, headers, and request behavior.\n* **Extensibility:** Can be integrated with other libraries and frameworks to fit various application architectures.\n\n### Benefits\n* **Centralized Data Access:** Provides a single source of truth for application data, ensuring consistency and reducing data duplication.\n* **Improved Performance:** Caching and optimized request management enhance application speed.\n* **Enhanced Developer Experience:** Simplifies data management and reduces boilerplate code.\n* **Flexibility:** Can be used across different components and parts of an application.\n* **Maintainability:** Promotes code organization and reduces potential inconsistencies.\n\nBy centralizing data management and offering flexible access to it, ARM empowers developers to build more efficient, scalable, and maintainable applications.\n\n## Basic Usage\n```javascript\n// Example usage in ReactJS\n\nimport { observer } from 'mobx-react'\nimport { ARM } from '@components/arm-config-wrapper'\n\nconst App = observer(() =\u003e {\n  const { isLoading, isError, data: address } = ARM.findRecord(\n    'addresses',\n    123456,\n    { include: 'user' },\n    { alias: 'customerAddress' }\n  )\n\n  return (\n    \u003cdiv className=\"App\"\u003e\n      {isLoading \u0026\u0026 \u003cspan\u003eLoading...\u003c/span\u003e}\n      {!isLoading \u0026\u0026 (\n        \u003cdiv className=\"form\"\u003e\n          \u003clabel\u003eAddress1 \u003c/label\u003e\n          \u003cinput\n            value={address.get('attributes.address1')}\n            onChange={(event) =\u003e\n              address.set('attributes.address1', event.target.value)\n            }\n          /\u003e\n          \u0026nbsp;\n          \u003cbutton\n            onClick={() =\u003e {\n              address\n                .save()\n                .then((result) =\u003e console.log(result))\n                .catch((error) =\u003e console.log(error))\n            }}\n          \u003e\n            {address.get('isLoading') ? 'Saving' : 'Save'}\n          \u003c/button\u003e\n        \u003c/div\u003e\n      )}\n    \u003c/div\u003e\n  )\n})\n\nexport default App\n```\n## Installation\n```\nnpm install arm-js-library --save\n```\n## Dependency Packages\n```\nnpm install mobx-react --save\n```\n## Initialization and Configuration \n\n#### Initialization\n\nCreate `arm-config-wrapper` component that will store the new `ARM` instance.\u003cbr/\u003e\n\n* Store it on component wrapper `src/components/arm-config-wrapper/index.js` here's an [example](https://github.com/michaeljymsgutierrez/arm-js-library/blob/main/apps/create-next-app/src/components/arm-config-wrapper/index.js)\n    ```javascript\n    // Tag component wrapper as client for NextJS specific only\n    'use client'\n\n    // Create a new instance of ARM\n    import ApiResourceManager from 'arm-js-library'\n\n    // Create an array of collections to initialize\n    const collections = ['addresses', 'users']\n\n    // Export new instance of ARM for later utilization\n    export const ARM = new ApiResourceManager(collections)\n\n    // Main config wrapper\n    const ARMConfigWrapper = ({ children }) =\u003e {\n      return \u003c\u003e{children}\u003c/\u003e\n    }\n\n    export default ARMConfigWrapper\n    ```\n* For `NextJS` project, wrap root layout `src/app/layout.js` with `arm-config-wrapper` component here's an [example](https://github.com/michaeljymsgutierrez/arm-js-library/blob/main/apps/create-next-app/src/app/layout.js)\n    ```javascript\n    import dynamic from 'next/dynamic'\n\n    const ARMConfigWrapper = dynamic(\n      () =\u003e import('../components/arm-config-wrapper'),\n      { ssr: false }\n    )\n\n    export default function RootLayout({ children }) {\n      return (\n        \u003chtml lang=\"en\"\u003e\n          \u003cbody\u003e\n            \u003cARMConfigWrapper\u003e{children}\u003c/ARMConfigWrapper\u003e\n          \u003c/body\u003e\n        \u003c/html\u003e\n      )\n    }\n    ```\n* For non `NextJS` project, wrap root app `src/index.js` with `arm-config-wrapper` component.\n    ```javascript\n    import ARMConfigWrapper from '@components/arm-config-wrapper'\n    import ReactDOM from 'react-dom/client'\n    import App from './App'\n\n    const root = ReactDOM.createRoot(document.getElementById('root'))\n    root.render(\n      \u003cARMConfigWrapper\u003e\n        \u003cApp /\u003e\n      \u003c/ARMConfigWrapper\u003e\n    )\n    ```\n#### Configuration\n\nConfigure stored ARM instance from where you stored it, to be able to use it on your application.\n\n**Required configurations**\n* **setHost(value)**\n    ```javascript\n    // Set API endpoint host URL\n    // By default host is set to window.location.origin\n    ARM.setHost('https://www.test-demo.com')\n    ```\n* **setHeadersCommon(key, value)**\n    ```javascript\n    // Set common request headers required on calling API endpoints\n    // ie. Authoization, Content-Type, etc.\n    ARM.setHeadersCommon('Authorization', `${token}`)\n    ARM.setHeadersCommon('Content-Type', 'application/vnd.api+json')\n    ARM.setHeadersCommon('X-Client-Platform', 'Web')\n    ```\n* **setNamespace(value)**\n    ```javascript\n    // Set namespace for API endpoint host URL\n    // By default namespace is set to 'api/v1'\n    ARM.setNamespace('api/v1')\n    ```\n**Optional configurations**\n* **setGlobal(value)**\n    ```javascript\n    // Set ARM instace to global\n    // This will make ARM instance available on browser window object via window.ARM\n    // Example:\n    //  console.log(window.ARM)\n    ARM.setGlobal()\n    ```\n* **setPayloadIncludeReference(value)**\n    ```javascript\n    // Set payload included reference key\n    // Payload included reference key serve as mapper to determine what collection\n    // the data received belongs to\n    // Example:\n    //  {\n    //    data: [...],\n    //    included: [ { id: 1, type: 'addresses' } ]\n    //  }\n    ARM.setPayloadIncludeReference('type')\n    ```\n## Utilization\nTo be able to use ARM features. You have to import the stored ARM instance from `arm-config-wrapper` component.\n```javascript\n// ARM instance is stored on src/components/arm-config-wrapper/index.js\nimport { ARM } from '@components/arm-config-wrapper'\n```\n\n#### Request functions from server\n---\n\n* **query(resource, params, config)**\n    * Querying multiple records from the server.\n    * Support query params. - **required**\n    * Support config. - **optional**\n    ```javascript\n    ARM.query(\n      'addresses',\n      {\n        sort: '-id',\n        include: 'user',\n      },\n      {\n        alias: 'customerAddresses',\n      }\n    )\n    ```\n* **queryRecord(resource, params, config)**\n    * Querying for a single record from the server.\n    * Support query params. - **required**\n    * Support config. - **optional**\n    ```javascript\n    ARM.queryRecord(\n      'addresses',\n      {\n        id: 123456,\n        sort: '-id',\n        include: 'user',\n      },\n      { alias: 'customerAddress' }\n    )\n    ```\n* **findAll(resource, config)**\n    * Retrieving multiple records from the server.\n    * Support config. - **optional**\n    ```javascript\n    ARM.findAll('addresses', {\n      alias: 'customerAddresses',\n    })\n    ```\n* **findRecord(resource, id, params, config)**\n    * Retrieving single record from the server.\n    * Params ID by default. - **required**\n    * Support query params. - **required**\n    * Support config. - **optional**\n    ```javascript\n    ARM.findRecord(\n      'addresses',\n      123456,\n      { include: 'user' },\n      {\n        alias: 'customerAddress',\n      }\n    )\n    ```\n#### Passed Arguments: `Request functions from server`\n---\n```javascript\n    // Example: https://www.test-demo.com/api/v1/addresses/1?include=user\n    ARM.findRecord('addresses', 123456,\n      { \n        include: 'user' \n      },\n      {\n        skip: true,\n        alias: 'customerAddress',\n      }\n    )\n```\n* **resource - String**\n    * `https://www.test-demo.com/api/v1/` **addresses** `/1?include=user`\n    * Endpoint resource name.\n    * Serve as collection name defined on the collection intialization of ARM instance.\n* **id - Number**\n    * `https://www.test-demo.com/api/v1/addresses/` **1**`?include=user`\n    * Endpoint id parameter.\n* **params - Object**\n    * `https://www.test-demo.com/api/v1/addresses/1?` **include=user**\n    * Endpoint query string parameters.\n* **config - Object**\n    * Contains request config such as `(skip, alias, autoResolve, ignorePayload, override)` which are currently available.\n    ```javascript\n      {\n        // Skip serve as request go signal to proceed \n        // if Request B has dependency on Request A\n        skip: true,\n\n        // Alias serve as identifier for the records obtain from the server.\n        // Can be used anywhere in your application through ARM.getAlias('customerAddress')\n        alias: 'customerAddress' ,\n\n        // Auto resolve serve as flag if the request functions will return \n        // 1. Promise Function\n        //  - To handle success and errors on manual resolve) if autoResolve is set to false\n        // 2. Observable/Reactive Data\n        //  - To handle success and errors on auto resolve) if autoResolve is set to true \n        // Note: autoResolve is only available on query, queryRecord, findAll, findRecord functions.\n        // By default autoResolve is set to true.\n        autoResolve: false,\n\n        // Ignore payload serve as list of keys to be omitted on request payload.\n        ignorePayload: ['attributes.address2', 'attributes.address1'],\n\n        // Override serve as request override for the default configuration of axios current request.\n        // Currently support host, namespace, path and headers for the meantime.\n        // Example:\n        // Before override: https://www.test-demo.com/api/v1/users/1\n        // After override: https://www.another-test-demo.com/api/v2/update-users/1\n        override: {\n          host: 'https://www.another-test-demo.com',\n          namespace: 'api/v2',\n          path: `update-users/${user.get('id')}`,\n          headers: {\n            'X-Client-Platform': 'Symbian',\n          }\n        }\n      }\n    ```\n#### Returned Object: `Request functions from server`\n---\n\n* **isLoading - Boolean**\n    * Current loading state of the request.\n    * By default set to **true**.\n    * Set to **true** once the request is initiated and set to **false** once request is done.\n* **isError - Boolean**\n    * Current error state of the request.\n    * By default set to **false**.\n    * Set to **true** if the request received/encountered an error and set to **false** if none.\n* **isNew - Boolean**\n    * Identifier if the request is newly created.\n    * By default set to **true**.\n    * Set to **true** if the request is already initiated once and set to **false** once it is already intiated before. \n      Request functions are built with optimization, it does not repeatedly executing API request.\n      Since it is optimized, it can be **override** using **skip** from request configuration.\n* **data - Array || Object**\n    * Contains the request returned payload.\n    * By default has value of an empty **array** or **object** depending on the request function used.\n* **error - Object || String**\n    * Contains the request returned error.\n    * By default has value of a **null**.\n* **included - Array**\n    * Contains the request returned payload property **included**.\n    * Specifically for **JSON API**.\n* **meta - Object**\n    * Contains the request returned payload property **meta**.\n    * Specifically for **JSON API**.\n* **reload - Function**\n    * Allows for **re-execution** of a request and automatic update of the **request hash object** and relevant **collections**.\n```javascript\n// Returned object data properties are observable\n// It will automatically update once the request is already done\n{\n  isLoading: true,\n  isError: false,\n  isNew: true,\n  data: [],\n  error: null,\n  included: [],\n  meta: {},\n  reload: function\n}\n```\n\n#### Retrieve functions from collections\n---\n\n* **peekAll(collectionName)**\n    * Retrieving multiple records from collection.\n    ```javascript\n    ARM.peekAll('addresses')\n    ```\n* **peekRecord(collectionName, collectionRecordId)**\n    * Retrieving single record from collection.\n    * Params ID by default. - **required**\n    ```javascript\n    ARM.peekRecord('addresses', 123456)\n    ```\n* **getCollection(collectionName)**\n    * Retrieving all records from collection.\n    ```javascript\n    ARM.getCollection('addresses')\n    ```\n* **getAlias(collectionName, collectionFallbackRecord)**\n    * Retrieving records from aliased request results.\n    * Support collectionFallbackRecord. - **optional**\n    ```javascript\n    const addresses = ARM.getAlias('customerAddresses', [])\n\n    ARM.findAll('addresses', { alias: 'customerAddresses' })\n\n    \u003cul\u003e\n      {addresses.map((address, index) =\u003e (\n        \u003cli key={index}\u003e{address.get('id')}\u003c/li\u003e\n      ))}\n    \u003c/ul\u003e\n    ```\n#### Create collection record function\n---\n* **createRecord(collectionName, collectionRecord, collectionRecordRandomId)**\n    * Create new collection record.\n    * By default collectionRecord params is set to empty object if omitted - **required**\n    * By default collectionRecordRandomId params is set to true - **optional**\n    ```javascript\n    // Usage #1\n    // Can ommit collectionRecord on createRecord initialization\n    const newAddress = ARM.createRecord('addresses')\n    newAddress.set('attributes.kind', 'school')\n    newAddress.set('attributes.label', 'My school')\n\n    // Usage #2\n    // Can ommit collectionRecord on createRecord initialization\n    const newAddress = ARM.createRecord('addresses', {\n      attributes: { kind: 'school', label: 'My school' }\n    })\n\n    // Persist collection record to server.\n    // Will call POST /addresses\n    newAddress.save()\n    ```\n#### Remove collection record functions\n---\n* **unloadRecord(collectionRecord)**\n    * Remove record from collection only.\n    ```javascript\n    // Collection record to be remove collection.\n    const address = ARM.peekRecord('addresses', 123456)\n\n    // This will remove the record from collection and will not\n    // remove permanently from the server.\n    ARM.unloadRecord(address)\n    ```\n* **clearCollection(collectionName)**\n    * Clears a specified collection and unloads related records from aliases and request hashes.\n    ```javascript\n    ARM.clearCollection('addresses')\n    ```\n#### Push collection record function\n---\n* **pushPayload(collectionName, collectionRecords)**\n    * Push raw collection record/records to respective collections.\n    ```javascript\n    // Retrieve raw data with barebone ajax/fetch function.\n    ARM.ajax({\n      method: 'get',\n      url: 'addresses/12345'\n    }).then(results =\u003e {\n      // Will add/update collection records.\n      ARM.pushPayload('addresses', results.data.data)\n    })\n    ```\n#### Collection Records: `Properties and Functions`\n---\n```javascript\n// Example response data from API\n// See available properties, getter and  setter functions and request functions below.\n{\n  \"id\": 123456,\n  \"type\": \"addresses\",\n  \"attributes\": {\n    \"address1\": \"Test Address 1\",\n    \"address2\": \"1718729541222\",\n    \"kind\": \"office\",\n    \"label\": \"Anabu Hills\",\n    \"latitude\": \"14.394261\",\n    \"longitude\": \"120.940783\"\n  }\n}\n```\n* **State Properties**\n    * **isLoading - Boolean**\n        * Current loading state of the record.\n        * By default set to **false**.\n        * Set to **true** once request functions **(save, reload, destroyRecord)** are initiated and set to **false** once done.\n        ```javascript\n        address.get('isLoading')\n        ```\n    * **isError - Boolean**\n        * Current error state of the record.\n        * By default set to **false**.\n        * Set to **true** once request functions **(save, reload, destroyRecord)** received an error and set to **false** if none.\n        ```javascript\n        address.get('isError')\n        ```\n    * **isPristine - Boolean**\n        * Current pristine state of the record.\n        * By default set to **true**.\n        * Set to **false** if the record is modified and set to **true** once reverted.\n        ```javascript\n        address.get('isPristine')\n        ```\n    * **isDirty - Boolean**\n        * Current dirty state of the record.\n        * By default set to **false**.\n        * Set to **true** if the record is modified and set to **false** once reverted.\n        ```javascript\n        address.get('isDirty')\n        ```\n* **Getter and Setter Functions**\n    * **get(key)**\n        * Single property getter function.\n        * Passed arguments:\n            * **key - String**\n        ```javascript\n        // Returned value 123456\n        address.get('id') \n\n        // Returned value 'office'\n        address.get('attributes.label') \n        ```\n    * **set(key, value)**\n        * Single property setter function.\n        * Passed arguments:\n            * **key - String**\n            * **value - Primitive**\n        ```javascript\n        // Returned value 'office'\n        address.get('attributes.kind')\n\n        // Set property label of attributes\n        address.set('attributes.kind', 'school')\n\n        // Returned value 'office'\n        address.get('attributes.kind')\n        ```\n    * **setProperties(value)**\n        * Multiple properties setter function.\n        * Passed arguments:\n            * **value - Object**\n        ```javascript\n        // Returned value 'office'\n        address.get('attributes.kind')\n        // Returned value 'Anabu Hills'\n        address.get('attributes.label')\n\n        // Set properties label and kind of attributes\n        address.setProperties({\n          attributes: { kind: 'school', label: 'My School' }\n        })\n\n        // Returned value 'school'\n        address.get('attributes.kind')\n        // Returned value 'My School'\n        address.get('attributes.label')\n        ```\n* **Request Functions**\n    * **save(collectionConfig)**\n        * Persist collection record changes to server.\n        * Create a new record to server  only if it doesn't already exist in the database.\n            * Will call **POST** method: `POST /addresses`\n        * Update existing record to server.\n            * Will call **PUT** method: `PUT /addresses/123456`\n        * Support collectionConfig. - **optional**\n            * Available collectionConfig `(skip, alias, autoResolve, ignorePayload, override)`\n        ```javascript\n        // Returned promise\n        // Without collectionConfig\n        address.save()\n\n        // With collectionConfig\n        address.save({ ignorePayload: ['attributes.address2'] })\n        ```\n    * **reload()**\n        * Refresh collection record changes from server.\n            * Will call **GET** method: `GET /addresses/123456`\n        ```javascript\n        // Returned promise\n        address.reload()\n        ```\n    * **destroyRecord(collectionConfig)**\n        * Remove collection record permanently from server.\n            * Will call **GET** method: `DELETE /addresses/123456`\n        * Support collectionConfig. - **optional**\n            * Available collectionConfig `(skip, alias, autoResolve, ignorePayload, override)`\n        ```javascript\n        // Returned promise\n        // Without collectionConfig\n        address.destroyRecord()\n\n        // With collectionConfig\n        address.destroyRecord({\n          override: {\n            host: 'https://ww7.test-demo.com',\n            namespace: 'api/v2',\n            path: `destroy-addresses/${address.get('id')}`,\n          }\n        })\n        ```\n    * **getCollection(collectionName, collectionConfig)**\n        * Retrieve records from server automatically if **async** option value is set to true **true** on **collectionConfig**.\n        * Retrieve records that are already loaded on collection if **async** option value is set to **false** on **collectionConfig**.\n        * Passed arguments:\n            * **collectionName - String**\n            * **collectionConfig - Object**                 \n                * **referenceKey - String**\n                    * Collection record property mapping.\n                * **async - Boolean**\n                    * Flag for invoking request function on resolving not yet loaded records on collection.\n                * **filterBy - Object**\n                    * Filter return collection records based on passed filter properties.\n                * **sortBy - Array**\n                    * Sort returned collection records based on passed array of sort criteria.\n                * **config - Object**\n                    * Contains request config such as `(skip, alias, autoResolve, ignorePayload, override)` which are currently available.\n        ```javascript\n        // Get user record from the server but don't preload addresses records.\n        const { isLoading, data: user } = ARM.findRecord(\n          'users',\n          123456,\n          {\n            // include: 'user'\n          },\n          { alias: 'currentUser' }\n        )\n\n        // The getCollection function will populate records from collection\n        // and server depending on passed collectionConfig.\n        {!isLoading \u0026\u0026 (\n          \u003cul\u003e\n            {user\n              .getCollection('addresses', {\n                referenceKey: 'relationships.addresses.data',\n                async: true,\n                sortBy: ['id:desc'],\n                filterBy: {\n                  attributes: {\n                    'label': 'Test'\n                  }\n                },\n                override: {\n                  namespace: 'api/v2',\n                }\n              })\n              .map((address, index) =\u003e (\n                \u003cli key={index}\u003e{address.get('id')}\u003c/li\u003e\n              ))}\n          \u003c/ul\u003e\n        )}\n        ```\n\n## Root Scope Functions\nThe root scope is an object that can be used to store and manage global state. The Root Scope Functions provide a way to manage and access it.\n\n* **setRootScope(rootScopeProperty, rootScopeValue)**\n    * Sets a value on the root scope.\n    * Passed arguments:\n        * **rootScopeProperty - String**\n        * **rootScopeValue - Any**\n    ```javascript\n    // Set root scope property 'fullName' to 'John Doe'\n    ARM.setRootScope('fullName', 'John Doe')\n    ```\n\n* **getRootScope(rootScopeProperty)**\n    * Retrieves a value from the root scope.\n    * Passed arguments:\n        * **rootScopeProperty - String**\n    ```javascript\n    // Returns value 'John Doe'\n    ARM.getRootScope('fullName')\n    ```\n## Utility Functions\nCollection of utility functions that leverage Lodash for common data manipulation tasks.\nThese functions primarily focus on searching, filtering, sorting, and validating data within objects or arrays.\n\n#### Data Retrieval and Manipulation\n---\n```javascript\n// Example response data from API\nconst addresses = [\n   {\n     \"id\": 1,\n     \"attributes\": {\n       \"kind\": \"office\",\n       \"label\": \"My Office\",\n     }\n   },\n   {\n     \"id\": 2,\n     \"attributes\": {\n       \"kind\": \"school\",\n       \"label\": \"My School\",\n     }\n   },\n   {\n     \"id\": 3,\n     \"attributes\": {\n       \"kind\": \"school\",\n       \"label\": \"My Brother's School\",\n     }\n   }\n ]\n```\n* **findBy(objects, findProperties)**\n    * Finds the first element in the given array of objects that satisfies the provided find properties.\n    ```javascript\n    // Return record with id 1\n    ARM.findBy(addresses, { id: 1 })\n    ```\n* **findIndexBy(objects, findIndexProperties)**\n    * Returns the index of the first element in the given array of objects that satisfies the provided find properties.\n    ```javascript\n    // Return index number of record with id 1\n    ARM.findIndexBy(addresses, {\n      attributes: { kind: 'office' }\n    })\n    ```\n* **filterBy(objects, filterProperties)**\n    * Creates a new array with all elements from the given array of objects that pass the filter test implemented by the provided filter properties. \n    ```javascript\n    // Returns records with ids 2 and 3\n    ARM.filterBy(addresses, {\n      attributes: { kind: 'school' }\n    })\n    ```\n* **uniqBy(objects, uniqByProperty)**\n    * Removes **duplicate** objects from an array based on a unique property. \n    ```javascript\n    // Returns records with ids 1 and 2\n    ARM.uniqBy(addresses, 'attributes.kind')\n    ```\n* **uniq(values)**\n    * Removes **duplicate** values from an array.\n    ```javascript\n    // Returns array with 1,2,3\n    ARM.uniq([1, 2, 2, 3, 3, 3])\n    ```\n* **groupBy(objects, groupByProperty)**\n    * **Incorrectly** uses **uniqBy** instead of grouping objects by the specified property. \n    ```javascript\n    // Returns { school: [{ id: 2 }, { id: 3 }], office: [{ id: 1 }]} \n    ARM.groupBy(addresses, 'attributes.kind')\n    ```\n* **mapBy(objects, mapByProperty)**\n    * **Maps** an array of objects, extracting a specific property from each.\n    ```javascript\n    // Returns ['office', 'school', 'school']\n    ARM.mapBy(addresses, 'attributes.kind')\n    ```\n\n* **firstObject(objects)**\n    * Returns the **first element** from the given array of objects. If the array is empty, it returns **undefined**. \n    ```javascript\n    // Return record with id 1\n    ARM.firstObject(addresses)\n    ```\n* **lastObject(objects)**\n    * Returns the **last element** from the given array of objects. If the array is empty, it returns **undefined**. \n    ```javascript\n    // Return record with id 3\n    ARM.lastObject(addresses)\n    ```\n* **mergeObjects(objects, otherObjects)**\n    * Combines two arrays of objects into one, removing duplicates. \n    ```javascript\n    ARM.mergeObjects(addresses, otherAddresses)\n    ```\n* **chunkObjects(objects, chunkSize)**\n    * Splits an array of objects into smaller arrays of a given **size**. \n    ```javascript\n    ARM.chunkObjects(addresses, 2)\n    ```\n* **sortBy(objects, sortProperties)**\n    * Sorts the given array of objects by the specified sort properties. \n    ```javascript\n    // Returns records order by ids 1,2,3\n    ARM.sortBy(addresses, ['id:asc'])\n\n    // Returns records order by ids 3,2,1\n    ARM.sortBy(addresses, ['id:desc'])\n    ```\n* **ajax(config)**\n    * Axios instance under the hood with default ARM config.\n    * Config accepts all properties that can be passed on **axios.request** config.\n    ```javascript\n    // Return promise\n    ARM.ajax({\n      method: 'get',\n      baseURL: 'https://other-api.test-demo.com',\n      url: '/api/v1/addresses'\n    })\n    .then(results =\u003e console.log(results))\n    .catch(errors =\u003e console.log(errors))\n    ```\n#### Data Validation and Comparison\n\n* **isEmpty(value)**\n    * Checks if a value is considered empty **(null, undefined, empty string, empty array, or empty object)**. \n    ```javascript\n    // Return boolean value\n    ARM.isEmpty(value)\n    ```\n* **isPresent(value)**\n    * Returns the opposite of isEmpty. \n    ```javascript\n    // Return boolean value\n    ARM.isPresent(value)\n    ```\n* **isEqual(value, other)**\n    * Performs a deep comparison between two values to determine if they are equal. \n    ```javascript\n    // Return boolean value\n    ARM.isEqual(value, other)\n    ```\n* **isNumber(value)**\n    * Checks if a value is a **number**. \n    ```javascript\n    // Return boolean value\n    ARM.isNumber(value)\n    ```\n* **isNil(value)**\n    * Checks if a value is **null** or **undefined**. \n    ```javascript\n    // Return boolean value\n    ARM.isNil(value)\n    ```\n* **isNull(value)**\n    * Checks if a value is **null**. \n    ```javascript\n    // Return boolean value\n    ARM.isNull(value)\n    ```\n* **isGte(value, other)**\n    * Checks if the first value is **greater than or equal** to the second value. \n    ```javascript\n    // Return boolean value\n    ARM.isGte(value, other)\n    ```\n* **isGt(value, other)**\n    * Checks if the first value is **greater than** the second value. \n    ```javascript\n    // Return boolean value\n    ARM.isGt(value, other)\n    ```\n* **isLte(value, other)**\n    * Checks if the first value is **less than or equal** to the second value. \n    ```javascript\n    // Return boolean value\n    ARM.isLte(value, other)\n    ```\n* **isLt(value, other)**\n    * Checks if the first value is **less than** the second value. \n    ```javascript\n    // Return boolean value\n    ARM.isLt(value, other)\n    ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaeljymsgutierrez%2Farm-js-library","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichaeljymsgutierrez%2Farm-js-library","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaeljymsgutierrez%2Farm-js-library/lists"}