{"id":21406609,"url":"https://github.com/ringcentral/ringcentral-js-helpers","last_synced_at":"2026-03-11T00:32:43.173Z","repository":{"id":58226559,"uuid":"46457739","full_name":"ringcentral/ringcentral-js-helpers","owner":"ringcentral","description":"JavaScript Helper Functions for SDK","archived":false,"fork":false,"pushed_at":"2016-02-03T05:55:30.000Z","size":237,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-02-22T14:38:02.112Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/ringcentral.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-11-19T00:57:45.000Z","updated_at":"2024-06-12T02:33:30.000Z","dependencies_parsed_at":"2022-08-31T05:21:59.466Z","dependency_job_id":null,"html_url":"https://github.com/ringcentral/ringcentral-js-helpers","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ringcentral/ringcentral-js-helpers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringcentral%2Fringcentral-js-helpers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringcentral%2Fringcentral-js-helpers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringcentral%2Fringcentral-js-helpers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringcentral%2Fringcentral-js-helpers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ringcentral","download_url":"https://codeload.github.com/ringcentral/ringcentral-js-helpers/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringcentral%2Fringcentral-js-helpers/sbom","scorecard":{"id":776764,"data":{"date":"2025-08-11","repo":{"name":"github.com/ringcentral/ringcentral-js-helpers","commit":"f1e488265ad7c07eb0dddefd294765f37e6cdece"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/5 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-23T03:49:53.222Z","repository_id":58226559,"created_at":"2025-08-23T03:49:53.222Z","updated_at":"2025-08-23T03:49:53.222Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30363921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"ssl_error","status_checked_at":"2026-03-10T21:40:59.357Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-11-22T16:40:51.877Z","updated_at":"2026-03-11T00:32:43.157Z","avatar_url":"https://github.com/ringcentral.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Installation\n\nSDK can be used in 2 environments:\n\n1. [Browser](#1-set-things-up-in-browser)\n2. [NodeJS](#1-set-things-up-in-nodejs)\n\n## 1. Set things up in Browser\n\n### 1.1. Get the code\n\nPick the option that works best for you:\n\n- **Preferred way to install SDK is to use Bower**, all dependencies will be downloaded to `bower_components` directory:\n\n    ```sh\n    bower install ringcentral-helpers --save\n    ```Bower\n    \n- Donwload everything manually *(not recommended)*:\n    - [ZIP file with source code](https://github.com/ringcentral/ringcentral-js-client/archive/master.zip)\n\n## 1.2.a. Add scripts to HTML page\n\nYou can use bundle version (with PUBNUB and ES6 Promise included in main file).\n\nAdd this to your HTML:\n\n```html\n\u003cscript type=\"text/javascript\" src=\"path-to-scripts/ringcentral-helpers/build/ringcentral-helpers.js\"\u003e\u003c/script\u003e\n```\n\nUse the object:\n\n```js\nvar helpers = RingCentral.Helpers;\n```\n\n## 1.2.b. Set things up in Browser (if you use RequireJS in your project)\n\n```js\n// Add this to your RequireJS configuration file\nrequire.config({\n    paths: {\n        'ringcentral-helpers': 'path-to-scripts/ringcentral-helpers/build/ringcentral-helpers',\n    }\n});\n\n// Then you can use the SDK like any other AMD component\nrequire(['ringcentral-helpers'], function(helpers) {\n    // your code here\n});\n```\n\n## 2. Set things up in NodeJS\n\n1. Install the NPM package:\n\n    ```sh\n    npm install ringcentral-helpers --save\n    ```\n\n2. Require the SDK:\n\n    ```js\n    var helpers = require('ringcentral-helpers');\n    ```\n    \n***\n\n# Helpers\n\n## Abstract\n\nThe SDK provides a variety of different helpers to make it easier to alter, save, load, and delete data objects and\notherwise interact with the features of the API. Helpers are plain JavaScript objects that contain functions and useful\nproperties (e.g. constants).\n\n## Basic Functionality\n\nAll helpers are extensions to the base `Helper` object and have all of its functions, plus some overrides and extra\nfunctionality. See the documentation for each particular helper for information on available options and methods.\n\nFollowing is a deeper look at the `CallHelper` object.\n\n### Create a URL\n\n```js\nhelpers.call().createUrl(options, id);\n```\n\nCreates a URL that can be provided to the `Platform#apiCall()` method. Creation algorithm is based on options:\n\n* `{personal: true}` - Call log of the currently logged in extension\n* `{extensionId: '12345'}` - Call log of extension with the id `12345` (the logged in user must have admin permissions)\n\nFollowing are some example calls, along with the URLs that they would return:\n\n```js\nhelpers.call().createUrl(); // '/account/~/extension/~/call-log'\nhelpers.call().createUrl({personal: true}); // '/account/~/extension/~/call-log'\nhelpers.call().createUrl({extensionId: '12345'}); // '/account/~/extension/12345/call-log'\nhelpers.call().createUrl({extensionId: '12345'}, '67890'); // '/account/~/extension/12345/call-log/67890'\n```\n\n### Check if an object exists on the server\n\n```js\nhelpers.call().isNew(object);\n```\n\nIf the object exists on the server, then the `isNew` method will return false. The object is considered not new if it\nhas both ID and URI properties - this usually means that the object was returned from the server.\n\n```js\nhelpers.call().isNew({}); // false\nhelpers.call().isNew({id: '67890'}); // false\nhelpers.call().isNew({uri: '/account/~/extension/12345/call-log/67890'}); // false\nhelpers.call().isNew({id: '67890', uri: '/account/~/extension/12345/call-log/67890'}); // true\n```\n\n### Filter an array of objects\n\n```js\nhelpers.call().filter(options);\n```\n\n`CallHelper#filter(options)` returns a preconfigured function that can be used for the `fn` argument when calling the\n`filter` method (`Array.prototype.filter(fn)`) on an array of calls. The behavior of the filter may vary depending on\nthe `options` argument.\n\n```js\n// calls in an array of Call Log calls\nvar callsFilteredByDirection = calls.filter(Call.filter({direction: 'Inbound'}));\nvar callsFilteredByType = calls.filter(Call.filter({type: 'Voice'}));\n```\n\n### Sort an array of objects\n\n```js\nhelpers.call().comparator(options);\n```\n\n`CallHelper#comparator(options)` returns a preconfigured function that can be used for the `fn` argument when calling\nthe `sort` method (`Array.prototype.sort(fn)`) on an array of calls. The behavior of the filter may vary depending on\nthe `options` argument. By default, values are extracted simply as `item[options.sortBy]` as strings and sorted as\nstrings. Custom `options.extractFn` and `options.compareFn` functions may be specified.\n\n```js\n// calls in an array of Call Log calls\nvar callsSortedByStartTime = calls.sort(Call.comparator({sortBy: 'startTime'})); // or any other property\nvar callsSortedByDuration = calls.sort(Call.comparator({\n    compareFn: rcsdk.getList().numberComparator // compare as numbers\n})); // or any other property\n\n// filter and sort can be combined\nvar inboundCallsSortedByStartTime = calls\n    .filter(Call.filter({direction: 'Inbound'}))\n    .sort(Call.comparator({sortBy: 'startTime'}));\n```\n\n### Special methods - Get pre-configured Subscription objects for endpoints\n\nThese methods will provide `Subscription` objects with pre-bound events.\n\n```js\nvar subscription = helpers.presence().addEventsToSubscription({detailed: true}, '~');\n```\n\n```js\nvar subscription = helpers.message().addEventsToSubscription();\n```\n\nOnce you have a `Subscription` object, all you need to do next is register it by calling its `register` method:\n\n```js\nsubscription.register();\n```\n\n### Special methods - Convert ActiveCalls array of Presence into regular Calls\n\nAssume that `presence` is an object returned by one of Presence endpoints.\n\n```js\nvar calls = helpers.call().parsePresenceCalls(presence.activeCalls);\n```\n\n### Full Example\n\nFor this example, AngularJS will be used.\n\n```js\nvar platform = sdk.platform(),\n    Call = helpers.call();\n\n$scope.calls = [];\n$scope.nextPageExists = true;\n$scope.queryParams = {page: 1, perPage: 'max'}; // page and perPage may be set from template\n\n$scope.requestNextPage = function() { // can be called from template to request next page\n    $scope.queryParams.page++;\n    loadCalls();\n};\n\nfunction loadCalls() {\n\n    platform.send(Call.loadRequest(null, {\n        query: $scope.queryParams,\n    })).then(function(response) {\n\n        $scope.calls = response.data.records\n            .filter(Call.filter({direction: 'Inbound'}))\n            .sort(Call.comparator({sortBy: 'startTime'}));\n\n        $scope.nextPageExists = Call.nextPageExists(response.data); // feed raw data from server to helper function\n\n    }).catch(function(e) {\n        alert('Error', e.message);\n    });\n\n}\n\nloadCalls();\n```\n\n***\n\n# Model Relations\n\n## Abstract\n\nThe SDK allows easy establishment of relationships between objects, such as between a Message object and its associated\nContact objects, or a Presence object and its associated Extension object. How the relationship is resolved varies\nacross different types of objects. The resolving function is provided by helper objects of a certain type.\n\n## Relationship\n\nModels have relationships to other models.\n\nIn many cases, model relationships are merely through properties of a model that identify other models. The data for the\nassociated child models is not contained inside the data for the model and would need to be loaded with separate\nrequests to the server. This type of relationship is considered a weak relationship. To use an example, both the Message\nand Call models have relationships to the Contact model. Associated models should be loaded separately and may be\nassigned to appropriate properties dynamically on the client based upon some criteria through helpers.\n\nIn some cases, models may actually contain other models. In such cases, the data for the associated child models will be\ncontained inside the model's data in the form of a property. The server returns the data for the model and its contained\nchild models within the same API call. As examples of this, the Presence model contains an `extension` property and the\nAccount model contains an `operator` property, and these properties are both references to contained models of type\n`IExtensionShort`.\n\n## Examples\n\n### Abstract CallerInfo types and Contacts\n\n```js\nvar contacts = [{homePhone: '+(1)foo'}, ...], // homePhone may be formatted\n    callerInfos = [{phoneNumber: '1foo'}, ...]; // phoneNumber is not formatted\n\nhelpers.contact().attachToCallerInfos(callerInfos, contacts);\n```\n\nEach `callerInfo` object will get the new properties:\n \n1. `contact` \u0026mdash; matching contact\n2. `contactPhone` \u0026mdash; entry from `contact` that matched `phoneNumber` \n\n### Messages / Calls and Contacts\n\nFor Messages and Calls, optimized helper functions may be used: \n\n```js\nmessages = helpers.message().attachContacts(contacts, messages);\ncalls = helpers.call().attachContacts(contacts, calls);\n```\n\nThis will internally fetch a list of `callerInfos` and attach appropriate contacts to them.\n\n### Presence and Extensions\n\n`Presence` information may be attached to `extensions`, for example, when the application has loaded a list of\nextensions and a list of their associated presence. Each `extension` will be given a new `presence` property, which will\nlink to the presence object for the extension.\n\n```js\nextensions = helpers.presence().attachToExtensions(extensions, presences);\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fringcentral%2Fringcentral-js-helpers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fringcentral%2Fringcentral-js-helpers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fringcentral%2Fringcentral-js-helpers/lists"}