@qikdev/sdk 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +1 -1
  2. package/dist/access.html +16371 -0
  3. package/dist/api.html +1503 -0
  4. package/dist/auth.html +8455 -0
  5. package/dist/cache.html +1135 -0
  6. package/dist/content.html +10067 -0
  7. package/dist/files.html +3415 -0
  8. package/dist/filter.html +4973 -0
  9. package/dist/geo.html +3851 -0
  10. package/dist/global.html +328 -0
  11. package/dist/index.html +96 -0
  12. package/dist/main.js +2 -3
  13. package/dist/module-QikStorage-CookieStorageAdapter.html +1177 -0
  14. package/dist/module-QikStorage-LocalStorageAdapter.html +329 -0
  15. package/dist/module-QikStorage-StorageAdapter.html +3457 -0
  16. package/dist/module-QikStorage.html +1445 -0
  17. package/dist/qik.access.js.html +904 -0
  18. package/dist/qik.api.js.html +409 -0
  19. package/dist/{docs/qik.auth.js.html → qik.auth.js.html} +142 -104
  20. package/dist/qik.cache.js.html +125 -0
  21. package/dist/qik.content.js.html +967 -0
  22. package/dist/qik.core.js.html +322 -0
  23. package/dist/qik.files.js.html +249 -0
  24. package/dist/{docs/qik.filter.js.html → qik.filter.js.html} +2 -2
  25. package/dist/qik.geo.js.html +963 -0
  26. package/dist/qik.socket.js.html +451 -0
  27. package/dist/qik.storage.js.html +375 -0
  28. package/dist/qik.system.js.html +117 -0
  29. package/dist/qik.utils.js.html +1542 -0
  30. package/dist/socket.html +2975 -0
  31. package/dist/{docs/styles → styles}/jsdoc.css +2 -2
  32. package/dist/system.html +523 -0
  33. package/package.json +2 -2
  34. package/src/api/qik.socket.js +18 -12
  35. package/src/version.js +1 -1
  36. package/dist/docs/access.html +0 -3826
  37. package/dist/docs/api.html +0 -1356
  38. package/dist/docs/auth.html +0 -2180
  39. package/dist/docs/cache.html +0 -351
  40. package/dist/docs/content.html +0 -2560
  41. package/dist/docs/files.html +0 -779
  42. package/dist/docs/filter.html +0 -1355
  43. package/dist/docs/index.html +0 -96
  44. package/dist/docs/qik.access.js.html +0 -790
  45. package/dist/docs/qik.api.js.html +0 -511
  46. package/dist/docs/qik.cache.js.html +0 -131
  47. package/dist/docs/qik.content.js.html +0 -918
  48. package/dist/docs/qik.core.js.html +0 -301
  49. package/dist/docs/qik.files.js.html +0 -219
  50. package/dist/docs/qik.socket.js.html +0 -416
  51. package/dist/docs/qik.system.js.html +0 -117
  52. package/dist/docs/qik.utils.js.html +0 -1467
  53. package/dist/docs/socket.html +0 -810
  54. package/dist/docs/system.html +0 -197
  55. /package/dist/{docs/fonts → fonts}/Montserrat/Montserrat-Bold.eot +0 -0
  56. /package/dist/{docs/fonts → fonts}/Montserrat/Montserrat-Bold.ttf +0 -0
  57. /package/dist/{docs/fonts → fonts}/Montserrat/Montserrat-Bold.woff +0 -0
  58. /package/dist/{docs/fonts → fonts}/Montserrat/Montserrat-Bold.woff2 +0 -0
  59. /package/dist/{docs/fonts → fonts}/Montserrat/Montserrat-Regular.eot +0 -0
  60. /package/dist/{docs/fonts → fonts}/Montserrat/Montserrat-Regular.ttf +0 -0
  61. /package/dist/{docs/fonts → fonts}/Montserrat/Montserrat-Regular.woff +0 -0
  62. /package/dist/{docs/fonts → fonts}/Montserrat/Montserrat-Regular.woff2 +0 -0
  63. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  64. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
  65. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  66. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  67. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  68. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  69. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
  70. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  71. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  72. /package/dist/{docs/fonts → fonts}/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  73. /package/dist/{docs/scripts → scripts}/collapse.js +0 -0
  74. /package/dist/{docs/scripts → scripts}/linenumber.js +0 -0
  75. /package/dist/{docs/scripts → scripts}/nav.js +0 -0
  76. /package/dist/{docs/scripts → scripts}/polyfill.js +0 -0
  77. /package/dist/{docs/scripts → scripts}/prettify/Apache-License-2.0.txt +0 -0
  78. /package/dist/{docs/scripts → scripts}/prettify/lang-css.js +0 -0
  79. /package/dist/{docs/scripts → scripts}/prettify/prettify.js +0 -0
  80. /package/dist/{docs/scripts → scripts}/search.js +0 -0
  81. /package/dist/{docs/styles → styles}/prettify.css +0 -0
@@ -0,0 +1,1542 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+
5
+ <meta charset="utf-8">
6
+ <title>qik.utils.js - Documentation</title>
7
+
8
+
9
+ <script src="scripts/prettify/prettify.js"></script>
10
+ <script src="scripts/prettify/lang-css.js"></script>
11
+ <!--[if lt IE 9]>
12
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13
+ <![endif]-->
14
+ <link type="text/css" rel="stylesheet" href="styles/prettify.css">
15
+ <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
16
+ <script src="scripts/nav.js" defer></script>
17
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
18
+ </head>
19
+ <body>
20
+
21
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
22
+ <label for="nav-trigger" class="navicon-button x">
23
+ <div class="navicon"></div>
24
+ </label>
25
+
26
+ <label for="nav-trigger" class="overlay"></label>
27
+
28
+ <nav >
29
+
30
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="access.html">access</a><ul class='methods'><li data-type='method'><a href="access.html#.actionableScopes">actionableScopes</a></li><li data-type='method'><a href="access.html#.actionableScopes">actionableScopes</a></li><li data-type='method'><a href="access.html#.allPermissions">allPermissions</a></li><li data-type='method'><a href="access.html#.allPermissions">allPermissions</a></li><li data-type='method'><a href="access.html#.allPermissionTypes">allPermissionTypes</a></li><li data-type='method'><a href="access.html#.allPermissionTypes">allPermissionTypes</a></li><li data-type='method'><a href="access.html#.allUserScopes">allUserScopes</a></li><li data-type='method'><a href="access.html#.allUserScopes">allUserScopes</a></li><li data-type='method'><a href="access.html#.canCreate">canCreate</a></li><li data-type='method'><a href="access.html#.canCreate">canCreate</a></li><li data-type='method'><a href="access.html#.canDeleteItem">canDeleteItem</a></li><li data-type='method'><a href="access.html#.canDeleteItem">canDeleteItem</a></li><li data-type='method'><a href="access.html#.canEditItem">canEditItem</a></li><li data-type='method'><a href="access.html#.canEditItem">canEditItem</a></li><li data-type='method'><a href="access.html#.canEraseItem">canEraseItem</a></li><li data-type='method'><a href="access.html#.canEraseItem">canEraseItem</a></li><li data-type='method'><a href="access.html#.canKnowOf">canKnowOf</a></li><li data-type='method'><a href="access.html#.canKnowOf">canKnowOf</a></li><li data-type='method'><a href="access.html#.canListItem">canListItem</a></li><li data-type='method'><a href="access.html#.canListItem">canListItem</a></li><li data-type='method'><a href="access.html#.canRestoreItem">canRestoreItem</a></li><li data-type='method'><a href="access.html#.canRestoreItem">canRestoreItem</a></li><li data-type='method'><a href="access.html#.canViewItem">canViewItem</a></li><li data-type='method'><a href="access.html#.canViewItem">canViewItem</a></li><li data-type='method'><a href="access.html#.checkActionAccess">checkActionAccess</a></li><li data-type='method'><a href="access.html#.checkActionAccess">checkActionAccess</a></li><li data-type='method'><a href="access.html#.getAllDescendants">getAllDescendants</a></li><li data-type='method'><a href="access.html#.getAllDescendants">getAllDescendants</a></li><li data-type='method'><a href="access.html#.has">has</a></li><li data-type='method'><a href="access.html#.has">has</a></li><li data-type='method'><a href="access.html#.hasFeature">hasFeature</a></li><li data-type='method'><a href="access.html#.hasFeature">hasFeature</a></li><li data-type='method'><a href="access.html#.hashPermissions">hashPermissions</a></li><li data-type='method'><a href="access.html#.hashPermissions">hashPermissions</a></li><li data-type='method'><a href="access.html#.isAdministrator">isAdministrator</a></li><li data-type='method'><a href="access.html#.isAdministrator">isAdministrator</a></li><li data-type='method'><a href="access.html#.isAssignee">isAssignee</a></li><li data-type='method'><a href="access.html#.isAssignee">isAssignee</a></li><li data-type='method'><a href="access.html#.isOwner">isOwner</a></li><li data-type='method'><a href="access.html#.isOwner">isOwner</a></li></ul></li><li></li><li><a href="api.html">api</a><ul class='methods'><li data-type='method'><a href="api.html#.generateEndpointURL">generateEndpointURL</a></li><li data-type='method'><a href="api.html#.generateEndpointURL">generateEndpointURL</a></li></ul></li><li></li><li><a href="auth.html">auth</a><ul class='methods'><li data-type='method'><a href="auth.html#.changeOrganisation">changeOrganisation</a></li><li data-type='method'><a href="auth.html#.changeOrganisation">changeOrganisation</a></li><li data-type='method'><a href="auth.html#.ensureValidToken">ensureValidToken</a></li><li data-type='method'><a href="auth.html#.ensureValidToken">ensureValidToken</a></li><li data-type='method'><a href="auth.html#.getCurrentToken">getCurrentToken</a></li><li data-type='method'><a href="auth.html#.getCurrentToken">getCurrentToken</a></li><li data-type='method'><a href="auth.html#.getCurrentUser">getCurrentUser</a></li><li data-type='method'><a href="auth.html#.getCurrentUser">getCurrentUser</a></li><li data-type='method'><a href="auth.html#.impersonate">impersonate</a></li><li data-type='method'><a href="auth.html#.impersonate">impersonate</a></li><li data-type='method'><a href="auth.html#.login">login</a></li><li data-type='method'><a href="auth.html#.login">login</a></li><li data-type='method'><a href="auth.html#.logout">logout</a></li><li data-type='method'><a href="auth.html#.logout">logout</a></li><li data-type='method'><a href="auth.html#.retrieveUserFromResetToken">retrieveUserFromResetToken</a></li><li data-type='method'><a href="auth.html#.retrieveUserFromResetToken">retrieveUserFromResetToken</a></li><li data-type='method'><a href="auth.html#.sendResetPasswordRequest">sendResetPasswordRequest</a></li><li data-type='method'><a href="auth.html#.sendResetPasswordRequest">sendResetPasswordRequest</a></li><li data-type='method'><a href="auth.html#.set">set</a></li><li data-type='method'><a href="auth.html#.set">set</a></li><li data-type='method'><a href="auth.html#.sync">sync</a></li><li data-type='method'><a href="auth.html#.sync">sync</a></li><li data-type='method'><a href="auth.html#.updateUserWithToken">updateUserWithToken</a></li><li data-type='method'><a href="auth.html#.updateUserWithToken">updateUserWithToken</a></li></ul></li><li></li><li><a href="cache.html">cache</a><ul class='methods'><li data-type='method'><a href="cache.html#.get">get</a></li><li data-type='method'><a href="cache.html#.get">get</a></li><li data-type='method'><a href="cache.html#.reset">reset</a></li><li data-type='method'><a href="cache.html#.reset">reset</a></li></ul></li><li></li><li><a href="content.html">content</a><ul class='methods'><li data-type='method'><a href="content.html#.create">create</a></li><li data-type='method'><a href="content.html#.create">create</a></li><li data-type='method'><a href="content.html#.delete">delete</a></li><li data-type='method'><a href="content.html#.delete">delete</a></li><li data-type='method'><a href="content.html#.get">get</a></li><li data-type='method'><a href="content.html#.get">get</a></li><li data-type='method'><a href="content.html#.getFromSlug">getFromSlug</a></li><li data-type='method'><a href="content.html#.getFromSlug">getFromSlug</a></li><li data-type='method'><a href="content.html#.glossary">glossary</a></li><li data-type='method'><a href="content.html#.glossary">glossary</a></li><li data-type='method'><a href="content.html#.list">list</a></li><li data-type='method'><a href="content.html#.list">list</a></li><li data-type='method'><a href="content.html#.patch">patch</a></li><li data-type='method'><a href="content.html#.patch">patch</a></li><li data-type='method'><a href="content.html#.restore">restore</a></li><li data-type='method'><a href="content.html#.restore">restore</a></li><li data-type='method'><a href="content.html#.scopeGlossary">scopeGlossary</a></li><li data-type='method'><a href="content.html#.scopeGlossary">scopeGlossary</a></li><li data-type='method'><a href="content.html#.update">update</a></li><li data-type='method'><a href="content.html#.update">update</a></li><li data-type='method'><a href="content.html#.validateField">validateField</a></li><li data-type='method'><a href="content.html#.validateField">validateField</a></li><li data-type='method'><a href="content.html#.variables">variables</a></li><li data-type='method'><a href="content.html#.variables">variables</a></li></ul></li><li></li><li><a href="files.html">files</a><ul class='methods'><li data-type='method'><a href="files.html#.downloadUrl">downloadUrl</a></li><li data-type='method'><a href="files.html#.downloadUrl">downloadUrl</a></li><li data-type='method'><a href="files.html#.duration">duration</a></li><li data-type='method'><a href="files.html#.duration">duration</a></li><li data-type='method'><a href="files.html#.filesize">filesize</a></li><li data-type='method'><a href="files.html#.filesize">filesize</a></li><li data-type='method'><a href="files.html#.getBinaryTypeFromMime">getBinaryTypeFromMime</a></li><li data-type='method'><a href="files.html#.getBinaryTypeFromMime">getBinaryTypeFromMime</a></li><li data-type='method'><a href="files.html#.mediaUrl">mediaUrl</a></li><li data-type='method'><a href="files.html#.mediaUrl">mediaUrl</a></li></ul></li><li></li><li><a href="filter.html">filter</a><ul class='methods'><li data-type='method'><a href="filter.html#.activeFilterKeys">activeFilterKeys</a></li><li data-type='method'><a href="filter.html#.activeFilterKeys">activeFilterKeys</a></li><li data-type='method'><a href="filter.html#.activeFilterKeys">activeFilterKeys</a></li><li data-type='method'><a href="filter.html#.activeFilterKeys">activeFilterKeys</a></li><li data-type='method'><a href="filter.html#.activeFilterOperators">activeFilterOperators</a></li><li data-type='method'><a href="filter.html#.activeFilterOperators">activeFilterOperators</a></li><li data-type='method'><a href="filter.html#.activeFilters">activeFilters</a></li><li data-type='method'><a href="filter.html#.activeFilters">activeFilters</a></li><li data-type='method'><a href="filter.html#.activeFilterValues">activeFilterValues</a></li><li data-type='method'><a href="filter.html#.activeFilterValues">activeFilterValues</a></li><li data-type='method'><a href="filter.html#.filterChangeString">filterChangeString</a></li><li data-type='method'><a href="filter.html#.filterChangeString">filterChangeString</a></li><li data-type='method'><a href="filter.html#.isValidFilter">isValidFilter</a></li><li data-type='method'><a href="filter.html#.isValidFilter">isValidFilter</a></li></ul></li><li></li><li><a href="geo.html">geo</a><ul class='methods'><li data-type='method'><a href="geo.html#.distance">distance</a></li><li data-type='method'><a href="geo.html#.distance">distance</a></li><li data-type='method'><a href="geo.html#.getDefaultCountry">getDefaultCountry</a></li><li data-type='method'><a href="geo.html#.getDefaultCountry">getDefaultCountry</a></li><li data-type='method'><a href="geo.html#.getDefaultTimezone">getDefaultTimezone</a></li><li data-type='method'><a href="geo.html#.getDefaultTimezone">getDefaultTimezone</a></li><li data-type='method'><a href="geo.html#.getPosition">getPosition</a></li><li data-type='method'><a href="geo.html#.getPosition">getPosition</a></li><li data-type='method'><a href="geo.html#.stopWatchPosition">stopWatchPosition</a></li><li data-type='method'><a href="geo.html#.stopWatchPosition">stopWatchPosition</a></li><li data-type='method'><a href="geo.html#.stopWatchPosition">stopWatchPosition</a></li><li data-type='method'><a href="geo.html#.stopWatchPosition">stopWatchPosition</a></li></ul></li><li></li><li><a href="module-QikStorage-CookieStorageAdapter.html">CookieStorageAdapter</a><ul class='methods'><li data-type='method'><a href="module-QikStorage-CookieStorageAdapter.html#getCookieOptions">getCookieOptions</a></li><li data-type='method'><a href="module-QikStorage-CookieStorageAdapter.html#getCookieOptions">getCookieOptions</a></li><li data-type='method'><a href="module-QikStorage-CookieStorageAdapter.html#isCookieMode">isCookieMode</a></li><li data-type='method'><a href="module-QikStorage-CookieStorageAdapter.html#isCookieMode">isCookieMode</a></li></ul></li><li></li><li><a href="module-QikStorage-LocalStorageAdapter.html">LocalStorageAdapter</a></li><li></li><li><a href="module-QikStorage-StorageAdapter.html">StorageAdapter</a><ul class='methods'><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#clearUser">clearUser</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#clearUser">clearUser</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#getAccessToken">getAccessToken</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#getAccessToken">getAccessToken</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#getRefreshToken">getRefreshToken</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#getRefreshToken">getRefreshToken</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#getTokenExpiry">getTokenExpiry</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#getTokenExpiry">getTokenExpiry</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#getUser">getUser</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#getUser">getUser</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#isAvailable">isAvailable</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#isAvailable">isAvailable</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#setUser">setUser</a></li><li data-type='method'><a href="module-QikStorage-StorageAdapter.html#setUser">setUser</a></li></ul></li><li></li><li><a href="socket.html">socket</a><ul class='methods'><li data-type='method'><a href="socket.html#.channel">channel</a></li><li data-type='method'><a href="socket.html#.channel">channel</a></li><li data-type='method'><a href="socket.html#.close">close</a></li><li data-type='method'><a href="socket.html#.close">close</a></li><li data-type='method'><a href="socket.html#.connect">connect</a></li><li data-type='method'><a href="socket.html#.connect">connect</a></li><li data-type='method'><a href="socket.html#.reconnect">reconnect</a></li><li data-type='method'><a href="socket.html#.reconnect">reconnect</a></li><li data-type='method'><a href="socket.html#.subscribe">subscribe</a></li><li data-type='method'><a href="socket.html#.subscribe">subscribe</a></li><li data-type='method'><a href="socket.html#.unsubscribe">unsubscribe</a></li><li data-type='method'><a href="socket.html#.unsubscribe">unsubscribe</a></li></ul></li><li></li><li><a href="system.html">system</a><ul class='methods'><li data-type='method'><a href="system.html#.countries">countries</a></li><li data-type='method'><a href="system.html#.countries">countries</a></li></ul></li><li></li></ul><h3>Modules</h3><ul><li><a href="module-QikStorage.html">QikStorage</a><ul class='methods'><li data-type='method'><a href="module-QikStorage.html#.createStorageAdapter">createStorageAdapter</a></li><li data-type='method'><a href="module-QikStorage.html#.createStorageAdapter">createStorageAdapter</a></li></ul></li><li></li></ul><h3>Global</h3><ul><li><a href="global.html#EventDispatcher">EventDispatcher</a></li></ul>
31
+ </nav>
32
+
33
+ <div id="main">
34
+
35
+ <h1 class="page-title">qik.utils.js</h1>
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+ <section>
44
+ <article>
45
+ <pre class="prettyprint source linenums"><code>import _get from "lodash.get";
46
+ import _camelCase from "lodash.camelcase";
47
+ import { isBrowser, isNode } from "browser-or-node";
48
+
49
+ ///////////////////////////////////////////////////////////////////////////////
50
+
51
+ const service = {};
52
+
53
+ ////////////////////////////////////
54
+
55
+ const loadedExternalScripts = {};
56
+
57
+ /**
58
+ * A function that dynamically include an external javascript resource
59
+ * ensuring that it will only be included once
60
+ * @alias utils.loadExternalScript
61
+ * @param {String} url The url of the external script
62
+ * @return {Promise} A promise that will be resolved once the script has been loaded
63
+ * @example
64
+ *
65
+ * await sdk.utils.loadExternalScript('https://cdn.javascript.com/external/script.js');
66
+ */
67
+
68
+ service.loadExternalScript = function (url) {
69
+ // If we already have a promise
70
+ if (loadedExternalScripts[url]) {
71
+ // return the existing promise
72
+ return loadedExternalScripts[url];
73
+ }
74
+
75
+ // Create a new promise
76
+ const promise = (loadedExternalScripts[url] = new Promise(createNewScript));
77
+
78
+ function createNewScript(resolve, reject) {
79
+ if (!document) {
80
+ delete loadedExternalScripts[url];
81
+ return reject("document is undefined");
82
+ }
83
+
84
+ //////////////////////////////////////
85
+
86
+ var script = document.createElement("script");
87
+ script.type = "text/javascript";
88
+ script.async = true;
89
+ script.onload = function () {
90
+ console.log("Loaded external script", url);
91
+ return resolve(url);
92
+ };
93
+ script.src = url;
94
+
95
+ // Inject it into the document's &lt;head> tag
96
+ document.head.appendChild(script);
97
+ }
98
+
99
+ return promise;
100
+ };
101
+
102
+ const loadedExternalStyles = {};
103
+
104
+ /**
105
+ * A function that dynamically include an external css resource
106
+ * ensuring that it will only be included once
107
+ * @alias utils.loadExternalStyle
108
+ * @param {String} url The url of the external css
109
+ * @return {Promise} A promise that will be resolved once the css has been loaded
110
+ * @example
111
+ *
112
+ * await sdk.utils.loadExternalStyle('https://cdn.css.com/external/style.css');
113
+ */
114
+ service.loadExternalStyle = function (url) {
115
+ const promise = new Promise(createNewScript);
116
+
117
+ function createNewScript(resolve, reject) {
118
+ if (!document) {
119
+ return reject("document is undefined");
120
+ }
121
+
122
+ if (loadedExternalStyles[url]) {
123
+ return resolve(url);
124
+ }
125
+
126
+ // Avoid duplicate scripts
127
+ loadedExternalStyles[url] = true;
128
+
129
+ //////////////////////////////////////
130
+
131
+ var script = document.createElement("link");
132
+ script.setAttribute("rel", "stylesheet");
133
+ script.setAttribute("type", "text/css");
134
+ script.setAttribute("href", url);
135
+ script.onload = function () {
136
+ console.log("Loaded external stylesheet", url);
137
+ return resolve(url);
138
+ };
139
+
140
+ // Inject it into the document's &lt;head> tag
141
+ document.head.appendChild(script);
142
+ }
143
+
144
+ return promise;
145
+ };
146
+
147
+ ///////////////////////////////////////////////////////////////////////////////
148
+
149
+ /**
150
+ * A helper function for checking whether a value is truthy/falsy
151
+ * @alias utils.exists
152
+ * @param {Anything} value The value to check
153
+ * @return {Boolean} whether the value is truthy
154
+ * @example
155
+ *
156
+ * sdk.utils.exists('undefined'); // false
157
+ * sdk.utils.exists([]); // true
158
+ * sdk.utils.exists(''); // false
159
+ * sdk.utils.exists(undefined); // false
160
+ */
161
+ service.exists = function (value) {
162
+ var isUndefinedOrNull;
163
+
164
+ ////////////////////////
165
+
166
+ if (Array.isArray(value)) {
167
+ return true;
168
+ }
169
+
170
+ ////////////////////////
171
+
172
+ if (value === 0) {
173
+ return true;
174
+ }
175
+
176
+ ////////////////////////
177
+
178
+ switch (typeof value) {
179
+ case "undefined":
180
+ case "null":
181
+ isUndefinedOrNull = true;
182
+ break;
183
+ default:
184
+ var string = String(value).toLowerCase();
185
+ switch (string) {
186
+ case "":
187
+ case "undefined":
188
+ case "null":
189
+ isUndefinedOrNull = true;
190
+ break;
191
+ }
192
+ break;
193
+ }
194
+
195
+ return !!!isUndefinedOrNull;
196
+ };
197
+
198
+ //////////////////////////////////
199
+
200
+ /**
201
+ * A helper function for getting a javascript date object from some input
202
+ * returns undefined if it can not be parsed
203
+ * @alias utils.parseDate
204
+ * @param {String|Number} input The value to parse as a date
205
+ * @return {Date} the javascript date object
206
+ * @example
207
+ *
208
+ * sdk.utils.parseDate(input);
209
+ */
210
+ service.parseDate = function (input) {
211
+ if (!input) {
212
+ return;
213
+ }
214
+
215
+ if (input instanceof Date) {
216
+ return input;
217
+ }
218
+
219
+ //Attempt to create a date
220
+ var d = new Date(input);
221
+ var isValid = d instanceof Date &amp;&amp; !isNaN(d);
222
+
223
+ if (isValid) {
224
+ return d;
225
+ }
226
+
227
+ return;
228
+ };
229
+
230
+ /**
231
+ * A helper function for getting a full url string from some input
232
+ * @alias utils.parseURL
233
+ * @param {String} input The input value
234
+ * @return {String} the fully parsed URL
235
+ * @example
236
+ *
237
+ * sdk.utils.parseURL('google.com'); // Returns https://google.com
238
+ * sdk.utils.parseURL('mailto:hello@qik.dev'); // Returns 'mailto:hello@qik.dev'
239
+ * sdk.utils.parseURL('://hello.com'); // Returns '://hello.com'
240
+ * sdk.utils.parseURL('hello@email.com'); // Returns 'mailto:hello@email.com'
241
+ */
242
+ service.parseURL = function (string) {
243
+ if (!string) {
244
+ return false;
245
+ }
246
+
247
+ const relative = string.startsWith("/");
248
+ if (relative) {
249
+ return string;
250
+ }
251
+
252
+ if (string.startsWith("://")) {
253
+ return string;
254
+ }
255
+
256
+ if (string.startsWith("mailto:")) {
257
+ return string;
258
+ }
259
+
260
+ if (string.startsWith("tel:")) {
261
+ return string;
262
+ }
263
+
264
+ if (string.startsWith("sms:")) {
265
+ return string;
266
+ }
267
+
268
+ //////////////////////////////////
269
+ //If someone entered an email by accident
270
+ var email = service.parseEmail(string);
271
+ //Convert it to a mailto link
272
+ if (email &amp;&amp; email === string) {
273
+ return `mailto:${email}`;
274
+ }
275
+
276
+ //////////////////////////////////
277
+
278
+ const withHttp = (string) =>
279
+ !/^https?:\/\//i.test(string) ? `http://${string}` : string;
280
+ string = withHttp(string);
281
+ //TODO: test this more.
282
+ string = string.replace(/\s/g, "");
283
+
284
+ var valid = RegExp(
285
+ "(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&amp;a-z\\d%_.~+=-@]*)?(\\#[-a-z\\d_@]*)?$",
286
+ "i",
287
+ ).test(string);
288
+
289
+ if (!valid) {
290
+ return false;
291
+ }
292
+
293
+ ///////////////////////////
294
+
295
+ return withHttp(string);
296
+ };
297
+
298
+ ///////////////////////////////////////////////
299
+
300
+ /**
301
+ * A helper function for getting a number from some input
302
+ * @alias utils.parseNumber
303
+ * @param {String} value The input value
304
+ * @param {Number} decimalPoints The number of decimal points to round to
305
+ * @return {Number} the parsed number value
306
+ * @example
307
+ *
308
+ * sdk.utils.parseNumber('123'); // Returns 123
309
+ * sdk.utils.parseNumber('75.501', 2); // Returns 75.5
310
+ * sdk.utils.parseNumber(''); // Returns 0
311
+ * sdk.utils.parseNumber(null); // Returns 0
312
+ * sdk.utils.parseNumber(); // Returns 0
313
+ */
314
+ service.parseNumber = function (input, decimalPoints) {
315
+ if (!input) {
316
+ return 0;
317
+ }
318
+
319
+ input = Number(input);
320
+ if (isNaN(input)) {
321
+ return 0;
322
+ }
323
+
324
+ if (decimalPoints) {
325
+ var str = input.toFixed(decimalPoints);
326
+ input = service.parseNumber(str);
327
+ }
328
+
329
+ return input;
330
+ };
331
+
332
+ /**
333
+ * A helper function for getting a number from some input
334
+ * @alias utils.isValidEmailAddress
335
+ * @param {String} emailAddress The email to validate
336
+ * @return {Boolean} whether or not the input is a valid email address
337
+ * @example
338
+ *
339
+ * sdk.utils.isValidEmailAddress('123.com'); // Returns false
340
+ * sdk.utils.isValidEmailAddress('hello@world.com'); // Returns true
341
+ * sdk.utils.isValidEmailAddress('something@special.io'); // Returns true
342
+ */
343
+ service.isValidEmailAddress = function (email) {
344
+ var tester =
345
+ /^[-!#$%&amp;'*+\/0-9=?A-Z^_a-z`{|}~](\.?[-!#$%&amp;'*+\/0-9=?A-Z^_a-z`{|}~])*@[a-zA-Z0-9](-*\.?[a-zA-Z0-9])*\.[a-zA-Z](-?[a-zA-Z0-9])+$/;
346
+
347
+ if (!email) return false;
348
+
349
+ var emailParts = email.split("@");
350
+
351
+ if (emailParts.length !== 2) return false;
352
+
353
+ var account = emailParts[0];
354
+ var address = emailParts[1];
355
+
356
+ if (account.length > 64) return false;
357
+ else if (address.length > 255) return false;
358
+
359
+ var domainParts = address.split(".");
360
+ if (
361
+ domainParts.some(function (part) {
362
+ return part.length > 63;
363
+ })
364
+ )
365
+ return false;
366
+
367
+ if (!tester.test(email)) return false;
368
+
369
+ return true;
370
+ };
371
+
372
+ /**
373
+ * A helper function for getting a formatted email address
374
+ * @alias utils.parseEmail
375
+ * @param {String} emailAddress The input to parse as an email
376
+ * @return {String|Boolean} a valid email address in lowercase, or false if parse is not possible
377
+ * @example
378
+ *
379
+ * sdk.utils.parseEmail('ToMack@gmail.com'); // returns 'tomack@gmail.com'
380
+ * sdk.utils.isValidEmailAddress('hello.world.com'); // Returns false
381
+ */
382
+ service.parseEmail = function (input) {
383
+ if (!input) {
384
+ return false;
385
+ }
386
+
387
+ var lowercase = String(input).toLowerCase();
388
+ var valid = service.isValidEmailAddress(lowercase);
389
+
390
+ if (!valid) {
391
+ return false;
392
+ } else {
393
+ return lowercase;
394
+ }
395
+ };
396
+
397
+ //////////////////////////////////
398
+
399
+ /**
400
+ * A helper function for getting an integer
401
+ * @alias utils.parseInt
402
+ * @param {String|Number} input The input to parse as an integer
403
+ * @return {Integer} the resulting integer or 0
404
+ * @example
405
+ *
406
+ * sdk.utils.parseInt('134'); // returns 134
407
+ * sdk.utils.parseInt('cows'); // returns 0
408
+ * sdk.utils.parseInt(); // returns 0
409
+ */
410
+ service.parseInt = function (input) {
411
+ if (!input) {
412
+ return 0;
413
+ }
414
+
415
+ input = parseInt(input);
416
+ if (isNaN(input)) {
417
+ return 0;
418
+ }
419
+
420
+ return input;
421
+ };
422
+
423
+ /**
424
+ * A helper function for cleaning an input value to match
425
+ * a required type
426
+ * @alias utils.cleanValue
427
+ * @param {*} data The input to clean
428
+ * @param {String} type The data type to parse
429
+ * @param {Object} options Additional options for parsing
430
+ * @return {*} the resulting cleaned value
431
+ * @example
432
+ *
433
+ * sdk.utils.cleanValue({_id:'1234', title:'Item'...}, 'reference'); // returns '1234'
434
+ * sdk.utils.cleanValue('true', 'boolean'); // returns true
435
+ * sdk.utils.cleanValue('Mr Rogers House', 'key'); // returns 'mrRogersHouse';
436
+ * sdk.utils.cleanValue('Hello.World@email.COM', 'email'); // returns 'hello.world@email.com';
437
+ */
438
+ service.cleanValue = function (data, type, options) {
439
+ if (!options) {
440
+ options = {};
441
+ }
442
+
443
+ ////////////////////////
444
+
445
+ var noInputValue = service.exists(data);
446
+ if (options.strict &amp;&amp; noInputValue &amp;&amp; type != "boolean") {
447
+ return data;
448
+ }
449
+
450
+ ////////////////////////
451
+
452
+ switch (type) {
453
+ case "reference":
454
+ return service.id(data, true);
455
+ break;
456
+ case "boolean":
457
+ return service.parseBoolean(data);
458
+ break;
459
+ case "url":
460
+ return service.parseURL(data);
461
+ break;
462
+ case "key":
463
+ return service.machineName(data);
464
+ break;
465
+ case "email":
466
+ return service.parseEmail(data);
467
+ break;
468
+ case "date":
469
+ var parsed = service.parseDate(data, options);
470
+
471
+ if (parsed === undefined) {
472
+ return;
473
+ } else {
474
+ return parsed;
475
+ }
476
+ break;
477
+ case "number":
478
+ case "decimal":
479
+ case "float":
480
+ var val = service.parseNumber(data);
481
+ if (String(val) == String(Number(data))) {
482
+ return val;
483
+ }
484
+ return;
485
+ break;
486
+ case "integer":
487
+ var val = service.parseInt(data);
488
+ if (String(val) == String(parseInt(data))) {
489
+ return val;
490
+ }
491
+ return;
492
+ break;
493
+ case "group":
494
+ return data;
495
+ break;
496
+ case "object":
497
+ if (typeof data === "object" &amp;&amp; data !== null &amp;&amp; !Array.isArray(data)) {
498
+ return data;
499
+ }
500
+
501
+ return;
502
+ break;
503
+ case "string":
504
+ if (service.exists(data)) {
505
+ var stringed = String(data);
506
+ if (stringed == "[object Object]") {
507
+ return;
508
+ }
509
+
510
+ return stringed;
511
+ } else {
512
+ return;
513
+ }
514
+
515
+ // if(!data) {
516
+ // return '';
517
+ // }
518
+
519
+ // if(Array.isArray(data)) {
520
+ // return JSON.stringify(data);
521
+ // }
522
+
523
+ // if(Object.isObject(data)) {
524
+ // return JSON.stringify(data);
525
+ // }
526
+
527
+ // return String(data);
528
+
529
+ // break;
530
+ default:
531
+ return String(data);
532
+ break;
533
+ }
534
+ };
535
+
536
+ service.isValidValue = function (value, dataType, strict) {
537
+ var isValue = service.exists(value);
538
+ var valueIsNumber = typeof value == "number";
539
+
540
+ ////////////////////////
541
+
542
+ var isValidEntry = false;
543
+
544
+ if (!isValue) {
545
+ return false;
546
+ }
547
+
548
+ ////////////////////////
549
+
550
+ switch (dataType) {
551
+ case "url":
552
+ if (strict) {
553
+ isValidEntry =
554
+ value.startsWith("/") ||
555
+ value.startsWith("://") ||
556
+ value.startsWith("http://") ||
557
+ value.startsWith("https://");
558
+ } else {
559
+ isValidEntry = String(value) === service.parseURL(value);
560
+ }
561
+ break;
562
+ case "key":
563
+ isValidEntry = String(value) === service.machineName(value);
564
+ break;
565
+ case "date":
566
+ //If we are being strict
567
+ if (strict) {
568
+ //And the input is not a javascript date object
569
+ if (typeof value != "object" || !(value instanceof Date)) {
570
+ return false;
571
+ }
572
+ }
573
+
574
+ ///////////////////////////////
575
+ var parsed = service.parseDate(value);
576
+ return parsed !== undefined;
577
+ break;
578
+ case "email":
579
+ if (strict) {
580
+ isValidEntry = value === service.parseEmail(value);
581
+ } else {
582
+ isValidEntry =
583
+ String(value).toLowerCase() === service.parseEmail(value);
584
+ }
585
+
586
+ break;
587
+ case "number":
588
+ case "decimal":
589
+ case "float":
590
+ if (strict) {
591
+ isValidEntry =
592
+ valueIsNumber &amp;&amp; Number(value) === service.parseNumber(value);
593
+ } else {
594
+ isValidEntry = Number(value) === service.parseNumber(value);
595
+ }
596
+ break;
597
+ case "integer":
598
+ if (strict) {
599
+ isValidEntry =
600
+ valueIsNumber &amp;&amp; Number(value) === service.parseInt(value);
601
+ } else {
602
+ isValidEntry = Number(value) === service.parseInt(value);
603
+ }
604
+ break;
605
+ case "boolean":
606
+ var parsed = service.parseBoolean(value);
607
+
608
+ //Only accept true booleans
609
+ if (strict) {
610
+ if (value === true || value === false) {
611
+ isValidEntry = value === parsed;
612
+ }
613
+ } else {
614
+ isValidEntry = parsed === true || parsed === false;
615
+ }
616
+ break;
617
+ case "reference":
618
+ if (strict) {
619
+ isValidEntry = String(value) === service.id(value);
620
+ } else {
621
+ isValidEntry = !!service.id(value);
622
+ }
623
+ break;
624
+ case "string":
625
+ var checkString = String(value);
626
+ if (strict) {
627
+ if (typeof value != "string") {
628
+ return false;
629
+ }
630
+ }
631
+
632
+ if (checkString == "[object Object]") {
633
+ return false;
634
+ }
635
+
636
+ isValidEntry = true;
637
+ break;
638
+ // case 'group':
639
+ // isValidEntry = _isObject(value);
640
+ // break;
641
+ case "object":
642
+ isValidEntry =
643
+ typeof value === "object" &amp;&amp; value !== null &amp;&amp; !Array.isArray(value);
644
+ break;
645
+ case "array":
646
+ isValidEntry = Array.isArray(value);
647
+ break;
648
+ }
649
+
650
+ ////////////////////////
651
+
652
+ return isValidEntry;
653
+ };
654
+
655
+ /**
656
+ * A helper function for parsing input as boolean values
657
+ * @alias utils.parseBoolean
658
+ * @param {*} value The input to parse
659
+ * @return {Boolean} the resulting true/false value
660
+ * @example
661
+ *
662
+ * sdk.utils.parseBoolean('true'); // returns true
663
+ * sdk.utils.parseBoolean('y'); // returns true
664
+ * sdk.utils.parseBoolean('YES'); // returns true
665
+ * sdk.utils.parseBoolean('1'); // returns true
666
+ * sdk.utils.parseBoolean('t'); // returns true
667
+ * sdk.utils.parseBoolean(''); // returns false
668
+ * sdk.utils.parseBoolean('0'); // returns false
669
+ * sdk.utils.parseBoolean('n'); // returns false
670
+ * sdk.utils.parseBoolean('no'); // returns false
671
+ * sdk.utils.parseBoolean('f'); // returns false
672
+ * sdk.utils.parseBoolean('null'); // returns false
673
+ */
674
+ service.parseBoolean = function (value) {
675
+ switch (String(value).toLowerCase()) {
676
+ case "true":
677
+ case "y":
678
+ case "yes":
679
+ case "1":
680
+ case "t":
681
+ value = true;
682
+ break;
683
+ case "false":
684
+ case "n":
685
+ case "no":
686
+ case "0":
687
+ case "f":
688
+ case "undefined":
689
+ case "null":
690
+ case "":
691
+ case "-1":
692
+ value = false;
693
+ break;
694
+ }
695
+
696
+ return !!value;
697
+ };
698
+
699
+ ///////////////////////////////////////////////////////////////////////////////
700
+
701
+ service.clone = function (input) {
702
+ return JSON.parse(JSON.stringify(input));
703
+ };
704
+
705
+ ///////////////////////////////////////////////////////////////////////////////
706
+
707
+ service.getAllFields = function (actualDefinition) {
708
+ const self = this;
709
+ const isProfile =
710
+ actualDefinition.definesType === "profile" ||
711
+ actualDefinition.key === "profile";
712
+ const isFormSubmission = actualDefinition.definesType === "submission";
713
+ var allFields = [...actualDefinition.fields];
714
+ var definedFields = actualDefinition.definedFields || [];
715
+
716
+ if (definedFields.length) {
717
+ if (isFormSubmission) {
718
+ var formDataFields = {
719
+ title: `Form Data`,
720
+ minimum: 1,
721
+ maximum: 1,
722
+ key: "formData",
723
+ asObject: true,
724
+ type: "group",
725
+ fields: definedFields,
726
+ };
727
+
728
+ allFields.push(formDataFields);
729
+
730
+ const cleanedDataFields = definedFields.map(function (field) {
731
+ if (field.type === "reference") {
732
+ field = JSON.parse(JSON.stringify(field));
733
+ delete field.fields;
734
+ }
735
+
736
+ return field;
737
+ });
738
+
739
+ var dataFields = {
740
+ title: `Data`,
741
+ minimum: 1,
742
+ maximum: 1,
743
+ key: "data",
744
+ asObject: true,
745
+ type: "group",
746
+ fields: cleanedDataFields,
747
+ };
748
+
749
+ allFields.push(dataFields);
750
+ } else {
751
+ var dataFields = {
752
+ title: `${actualDefinition.title}`,
753
+ minimum: 1,
754
+ maximum: 1,
755
+ key: "data",
756
+ asObject: true,
757
+ type: "group",
758
+ fields: definedFields,
759
+ };
760
+
761
+ allFields.push(dataFields);
762
+ }
763
+ }
764
+
765
+ if (isProfile) {
766
+ allFields.push({
767
+ title: "Age",
768
+ key: "_age",
769
+ minimum: 1,
770
+ maximum: 1,
771
+ type: "integer",
772
+ });
773
+
774
+ allFields.push({
775
+ title: "Date of birth",
776
+ key: "_dob",
777
+ minimum: 1,
778
+ maximum: 1,
779
+ type: "date",
780
+ });
781
+ }
782
+
783
+ var mapped = service
784
+ .mapFields(allFields)
785
+ .filter(function (field) {
786
+ var isObject =
787
+ field.type == "group" &amp;&amp;
788
+ field.asObject &amp;&amp;
789
+ field.minimum == 1 &amp;&amp;
790
+ field.maximum == 1;
791
+ return !isObject;
792
+ })
793
+ .map(function (field) {
794
+ field.title =
795
+ field.filterTitle || field.titles.filter(Boolean).join(" › ");
796
+
797
+ return field;
798
+ })
799
+ .sort(function (a, b) {
800
+ return a.title &lt; b.title ? -1 : 1;
801
+ });
802
+
803
+ return mapped;
804
+ };
805
+ ///////////////////////////////////////////////////////////////////////////////
806
+
807
+ service.mapFields = function (fields, options) {
808
+ if (!options) {
809
+ options = {};
810
+ }
811
+
812
+ //////////////////////////////
813
+
814
+ var output = [];
815
+ var trail = [];
816
+ var titles = [];
817
+ var currentDepth = 1;
818
+ var depthLimit = options.depth;
819
+ var delimiter = options.arrayDelimeter || "[]";
820
+
821
+ //Loop through each field
822
+ fields.forEach(mapField);
823
+
824
+ //////////////////////////////
825
+
826
+ //Recursively map the fields
827
+ function mapField(field, i) {
828
+ var fieldKey = field.key;
829
+ var isGroup = field.type == "group";
830
+ var singleValue = field.minimum === field.maximum &amp;&amp; field.minimum === 1;
831
+ var asObject = field.asObject; // || (isGroup &amp;&amp; singleValue);
832
+ var isLayout = isGroup &amp;&amp; !asObject;
833
+
834
+ //////////////////////////////////
835
+
836
+ // Whether to clone the field or use the existing reference
837
+ var mapped = options.original ? field : service.clone(field);
838
+
839
+ mapped.trail = trail.slice();
840
+ mapped.trail.push(fieldKey);
841
+
842
+ mapped.path = mapped.trail.join(".");
843
+ mapped.titles = titles.slice();
844
+ mapped.titles.push(field.filterTitle || field.title || "");
845
+
846
+ const isNotLayoutOrIsAllowed = !isLayout || options.includeLayout;
847
+
848
+ //If its an actual element or we've asked to include
849
+ //layout only elements
850
+ if (isNotLayoutOrIsAllowed) {
851
+ //Add it to the mix
852
+ output.push(mapped);
853
+ }
854
+
855
+ //////////////////////////////////
856
+
857
+ //Now see if there are child fields and should we go further
858
+ var limitHit = depthLimit &amp;&amp; currentDepth >= depthLimit;
859
+
860
+ //If there are child fields for this field
861
+ if (field.fields &amp;&amp; field.fields.length) {
862
+ //If it's just a group with no extra key
863
+ if (isLayout) {
864
+ //Loop through fields as if they are at the same depth
865
+ field.fields.forEach(mapField);
866
+ } else {
867
+ //We don't need to traverse any further
868
+ //because we hit the limit
869
+ if (limitHit) {
870
+ return;
871
+ }
872
+
873
+ //Move down a level and add to the object
874
+ //Include the key in the path trail
875
+ currentDepth++;
876
+
877
+ let injectKey = fieldKey;
878
+ if (options.includeArrayDelimeter) {
879
+ if (!singleValue) {
880
+ injectKey = `${fieldKey}${delimiter}`;
881
+ }
882
+ }
883
+ trail.push(injectKey);
884
+ titles.push(field.filterTitle || field.title);
885
+
886
+ //Loop through each field
887
+ field.fields.forEach(mapField);
888
+
889
+ //Move back up a level before we go to the next field
890
+ currentDepth--;
891
+ trail.pop();
892
+ titles.pop();
893
+ }
894
+ }
895
+ }
896
+
897
+ return output;
898
+ };
899
+
900
+ ///////////////////////////////////////////////////////////////////////////////
901
+
902
+ /**
903
+ * A helpful function that can take a keyed object literal and map it to url query string parameters
904
+ * @alias utils.mapParameters
905
+ * @param {Object} parameters The object you want to transalte
906
+ * @return {String} The query string
907
+ * @example
908
+ * //Returns &amp;this=that&amp;hello=world
909
+ * sdk.utils.mapParameters({"this":"that", "hello":"world"})
910
+ */
911
+ service.mapParameters = function (parameters) {
912
+ parameters = parameters || {};
913
+
914
+ var array = [];
915
+
916
+ Object.entries(parameters).forEach(function ([key, value]) {
917
+ if (value === undefined || value === null || value == false) {
918
+ return;
919
+ }
920
+
921
+ if (Array.isArray(value)) {
922
+ value.forEach(function (v) {
923
+ array.push(`${key}=${encodeURIComponent(v)}`);
924
+ });
925
+ } else {
926
+ array.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
927
+ }
928
+ });
929
+
930
+ return array.join("&amp;");
931
+ };
932
+
933
+ ///////////////////////////////////////////////////////////////////////////////
934
+
935
+ /**
936
+ * A function that will take an integer and a currency string and return a formatted numeric amount rounded to 2 decimal places
937
+ * @alias utils.formatCurrency
938
+ * @param {Integer} value The amount in cents
939
+ * @param {String} currency The currency to format
940
+ * @return {String} The formatted value
941
+ * @example
942
+ *
943
+ * //Returns £10.00
944
+ * sdk.utils.formatCurrency(1000, 'gbp');
945
+ *
946
+ * //Returns $10.00
947
+ * sdk.utils.formatCurrency(1000, 'usd');
948
+ *
949
+ */
950
+ service.formatCurrency = function (value, currency, decimalPoints) {
951
+ if (!value || isNaN(value)) {
952
+ value = 0;
953
+ }
954
+
955
+ decimalPoints = decimalPoints || 2;
956
+
957
+ var currencyPrefix = service.currencySymbol(currency);
958
+ return `${currencyPrefix}${parseFloat(Number(value) / 100).toFixed(decimalPoints)}`;
959
+ };
960
+
961
+ /**
962
+ * A function that will take an id and return the type key
963
+ * @alias utils.getTypeFromID
964
+ * @param {String} id The id of an object
965
+ * @return {String} The key
966
+ * @example
967
+ *
968
+ * // Returns 'user'
969
+ * sdk.utils.getTypeFromID('52b523f775beea960013f6cd');
970
+ *
971
+ * // Returns 'role'
972
+ * sdk.utils.getTypeFromID('62b59cb572fb4772e7b5fa93');
973
+ *
974
+ */
975
+ service.getTypeFromID = function (id) {
976
+ id = service.id(id);
977
+
978
+ if (!id) {
979
+ return;
980
+ }
981
+
982
+ const lookup = {
983
+ 21: "organisation",
984
+ 23: "comment",
985
+ 24: "persona",
986
+ 25: "audio",
987
+ 26: "campaign",
988
+ 28: "smartlist",
989
+ 29: "cache",
990
+ 40: "application",
991
+ 41: "action",
992
+ 42: "billinginvoice",
993
+ 43: "componentsnapshot",
994
+ 44: "diff",
995
+ 45: "email",
996
+ 46: "submission",
997
+ 49: "import",
998
+ 53: "socket",
999
+ 54: "timetrigger",
1000
+ 61: "article",
1001
+ 63: "component",
1002
+ 65: "event",
1003
+ 66: "file",
1004
+ 67: "tag",
1005
+ 69: "image",
1006
+ 70: "profile",
1007
+ 72: "role",
1008
+ 73: "scope",
1009
+ 74: "transaction",
1010
+ 75: "user",
1011
+ 76: "video",
1012
+ 77: "workflowcard",
1013
+ 78: "variable",
1014
+ "3c": "patoken",
1015
+ "7b": "uatoken",
1016
+ "7d": "urtoken",
1017
+ "2d": "systemtask",
1018
+ "3d": "export",
1019
+ "5f": "systemflag",
1020
+ "2b": "batch",
1021
+ "3a": "log",
1022
+ "2e": "stat",
1023
+ "2f": "unsubscribe",
1024
+ "6b": "intent",
1025
+ "7c": "upload",
1026
+ "2c": "systemtrigger",
1027
+ "6e": "interface",
1028
+ "4e": "interfacesnapshot",
1029
+ "4f": "notification",
1030
+ "2a": "definition",
1031
+ "7e": "definitionsnapshot",
1032
+ "5e": "integration",
1033
+ "4c": "listener",
1034
+ "6d": "topic",
1035
+ "7a": "code",
1036
+ "4d": "paymentmethod",
1037
+ "6c": "sslcertificate",
1038
+ };
1039
+
1040
+ var hexKey = id.slice(8, 10);
1041
+ return lookup[hexKey];
1042
+ };
1043
+
1044
+ /**
1045
+ * A function that will take a currency string and return the symbol
1046
+ * @alias utils.currencySymbol
1047
+ * @param {String} currency The currency
1048
+ * @return {String} The symbol
1049
+ * @example
1050
+ *
1051
+ * //Returns £
1052
+ * sdk.utils.currencySymbol('gbp');
1053
+ *
1054
+ * //Returns $
1055
+ * sdk.utils.currencySymbol('usd');
1056
+ *
1057
+ */
1058
+ const CURRENCY_SYMBOLS = { gbp: "\u00A3", eur: "\u20AC" };
1059
+
1060
+ service.currencySymbol = function (currency) {
1061
+ return CURRENCY_SYMBOLS[String(currency).toLowerCase()] || "$";
1062
+ };
1063
+
1064
+ const SUPPORTED_CURRENCIES = [
1065
+ { code: "usd", countries: ["US"] },
1066
+ { code: "gbp", countries: ["GB", "UK"] },
1067
+ { code: "cad", countries: ["CA"] },
1068
+ { code: "aud", countries: ["AU"] },
1069
+ { code: "nzd", countries: ["NZ"] },
1070
+ { code: "sgd", countries: ["SG"] },
1071
+ ];
1072
+
1073
+ service.getAvailableCurrencies = function (defaultCountryID) {
1074
+ let currencies = SUPPORTED_CURRENCIES.map(({ code, countries }) => ({
1075
+ name: `${code.toUpperCase()} (${service.currencySymbol(code)})`,
1076
+ value: code,
1077
+ countryCode: Object.fromEntries(countries.map((c) => [c, true])),
1078
+ }));
1079
+
1080
+ if (defaultCountryID) {
1081
+ const idx = currencies.findIndex((c) => c.countryCode[defaultCountryID]);
1082
+ if (idx > 0) {
1083
+ const [match] = currencies.splice(idx, 1);
1084
+ currencies.unshift(match);
1085
+ }
1086
+ }
1087
+
1088
+ return currencies;
1089
+ };
1090
+
1091
+ ///////////////////////////////////////////////////////////////////////////////
1092
+
1093
+ /**
1094
+ * Creates a fast keyed hash object from an array of items
1095
+ * @alias utils.hash
1096
+ * @param {Array} array The array of items to convert into a hash
1097
+ * @param {String} key The key or path to the property on each item to use as the hashed key
1098
+ * @return {Object} A key/value paired object
1099
+ * @example
1100
+ * //Returns { jimbo:{id:'jimbo', title:'Jim Jones'}, {id:'roger', title:'Roger Fellow'} }
1101
+ * sdk.utils.hash([{id:'jimbo', title:'Jim Jones'}, {id:'roger', title:'Roger Fellow'}], 'id');
1102
+ *
1103
+ */
1104
+ service.hash = function (items, key) {
1105
+ items = !Array.isArray(items) ? [] : items;
1106
+ return items.reduce(function (memo, item) {
1107
+ const k = key ? _get(item, key) : item;
1108
+ memo[k] = item;
1109
+ return memo;
1110
+ }, {});
1111
+ };
1112
+
1113
+ //////////////////////////////////////////////////
1114
+
1115
+ /**
1116
+ * Returns a subset of values in an array that match a provided rule
1117
+ * @alias utils.extractFromArray
1118
+ * @param {Array} array The array you want to extract values from
1119
+ * @param {String} key The path to the child property you want to extract
1120
+ * @param {Boolean} sum Whether to sum the extracted values together in total
1121
+ * @param {Boolean} flatten Whether to flatten nested child arrays
1122
+ * @param {Boolean} unique Whether to only return unique values
1123
+ * @param {Boolean} exclude Whether to exclude null or undefined values
1124
+ * @param {Object} options Pass through extra options for how to extract the values
1125
+ * @return {Array} An array of all values retrieved from the array, unless provided arguments require otherwise
1126
+ * @example
1127
+ * //Returns [12, 45] as all the values
1128
+ * sdk.utils.extractFromArray([{name:'Wendy', age:12}, {name:'Roger', age:45}], 'age');
1129
+ *
1130
+ * //Returns 32
1131
+ * sdk.utils.extractFromArray([{name:'Wendy', age:12}, {name:'Roger', age:20}], 'age', {sum:true});
1132
+ *
1133
+ */
1134
+ service.extractFromArray = function (
1135
+ array,
1136
+ key,
1137
+ sum,
1138
+ flatten,
1139
+ unique,
1140
+ exclude,
1141
+ options,
1142
+ ) {
1143
+ options = options || {};
1144
+
1145
+ if (sum) {
1146
+ options.sum = sum;
1147
+ }
1148
+
1149
+ if (flatten) {
1150
+ options.flatten = true;
1151
+ }
1152
+
1153
+ if (unique) {
1154
+ options.unique = true;
1155
+ }
1156
+
1157
+ if (exclude) {
1158
+ options.excludeNull = true;
1159
+ }
1160
+
1161
+ /////////////////
1162
+
1163
+ //Filter the array options by a certain value and operator
1164
+ var extractedValues = array.reduce(function (set, entry) {
1165
+ //Get the value from the object
1166
+ var retrievedValue = _get(entry, key);
1167
+
1168
+ var isNull =
1169
+ !retrievedValue &amp;&amp; retrievedValue !== false &amp;&amp; retrievedValue !== 0;
1170
+ if (options.excludeNull &amp;&amp; isNull) {
1171
+ return set;
1172
+ }
1173
+
1174
+ set.push(retrievedValue);
1175
+ return set;
1176
+ }, []);
1177
+
1178
+ if (options.flatten) {
1179
+ extractedValues = extractedValues.flat();
1180
+ }
1181
+
1182
+ if (options.unique) {
1183
+ extractedValues = [...new Set(extractedValues)];
1184
+ }
1185
+
1186
+ if (options.sum) {
1187
+ extractedValues = extractedValues.reduce(function (a, b) {
1188
+ return a + b;
1189
+ }, 0);
1190
+ }
1191
+
1192
+ return extractedValues;
1193
+ };
1194
+
1195
+ //////////////////////////////////////////////////////
1196
+
1197
+ /**
1198
+ * A function that can return a selection of values that were found in an array that match a specific rule,
1199
+ * This is often used to evaluate expressions within form fields
1200
+ * @alias utils.matchInArray
1201
+ * @param {Array} array The array to check
1202
+ * @param {String} key The javascript dot notation path to extract
1203
+ * @param {String} value The value to compare against
1204
+ * @param {String} comparator The logical operator to use to compare the extracted value with the provided value ('>', '&lt;', '>=', '&lt;=', 'in', '==') Defaults to '==' (Is equal to)
1205
+ * @return {Array} Returns an array of matching values
1206
+ * @example
1207
+ * //Returns [{name:'Michael', age:45}] as that is only item in the array that matches the criteria
1208
+ * sdk.utils.matchInArray([{name:'Wendy', age:12}, {name:'Michael', age:45}], 'age', 45, '>=');
1209
+ *
1210
+ */
1211
+ service.matchInArray = function (array, key, v, comparator) {
1212
+ //Filter the array options by a certain v and comparator
1213
+ var matches = array.filter(function (entry) {
1214
+ //Get the v from the object
1215
+ var extracted = _get(entry, key);
1216
+ var found;
1217
+
1218
+ switch (comparator) {
1219
+ case "in":
1220
+ found = extracted.includes(v);
1221
+ break;
1222
+ case ">=":
1223
+ found = extracted >= v;
1224
+ break;
1225
+ case "&lt;=":
1226
+ found = extracted &lt;= v;
1227
+ break;
1228
+ case "&lt;":
1229
+ found = extracted &lt; v;
1230
+ break;
1231
+ case ">":
1232
+ found = extracted > v;
1233
+ break;
1234
+ case "==":
1235
+ default:
1236
+ if (v === undefined) {
1237
+ found = extracted;
1238
+ } else {
1239
+ found = extracted == v;
1240
+ }
1241
+ break;
1242
+ }
1243
+
1244
+ return found;
1245
+ });
1246
+
1247
+ return matches;
1248
+ };
1249
+
1250
+ ///////////////////////////////////////////////////////////////////////////////
1251
+
1252
+ /**
1253
+ * A helpful class that can take an array of values and return them as a comma seperated
1254
+ * string, If the values are objects, then a property to use as the string representation can be specified
1255
+ * @alias utils.comma
1256
+ * @param {Array} array The array of values to translate
1257
+ * @param {String} path An optional property key to use for each value
1258
+ * @return {String} The resulting comma seperated string
1259
+ * @example
1260
+ * //Returns 'cat, dog, bird'
1261
+ * sdk.utils.comma(['cat', 'dog', 'bird']);
1262
+ *
1263
+ * //Returns 'cat, dog, bird'
1264
+ * sdk.utils.comma([{title:'cat'}, {title:'dog'}, {title:'bird'}], 'title');
1265
+ */
1266
+ service.comma = function (array, path, limit) {
1267
+ if (limit) {
1268
+ array = array.slice(0, limit);
1269
+ }
1270
+
1271
+ return array
1272
+ .filter(function (item) {
1273
+ return item != null &amp;&amp; item !== undefined &amp;&amp; item !== "";
1274
+ })
1275
+ .map(function (item) {
1276
+ if (path &amp;&amp; path.length) {
1277
+ return _get(item, path);
1278
+ }
1279
+
1280
+ return item;
1281
+ })
1282
+ .join(", ");
1283
+ };
1284
+
1285
+ ///////////////////////////////////////////////////////////////////////////////
1286
+
1287
+ //Helper function to get an id of an object
1288
+
1289
+ /**
1290
+ * Returns a specified _id for an object
1291
+ * @alias utils.id
1292
+ * @param {Object} input An object that is or has an _id property
1293
+ * @param {Boolean} asObjectID Whether to convert to a Mongo ObjectId
1294
+ * @return {String} Will return either a string or a Mongo ObjectId
1295
+ *
1296
+ * @example
1297
+ *
1298
+ * //Returns '5cb3d8b3a2219970e6f86927'
1299
+ * sdk.utils.id('5cb3d8b3a2219970e6f86927')
1300
+ *
1301
+ * //Returns true
1302
+ * typeof service.id({_id:'5cb3d8b3a2219970e6f86927', title, ...}) == 'string';
1303
+
1304
+ * //Returns true
1305
+ * typeof service.id({_id:'5cb3d8b3a2219970e6f86927'}, true) == 'object';
1306
+ */
1307
+ service.id = function (source) {
1308
+ if (!source) {
1309
+ return;
1310
+ }
1311
+
1312
+ /////////////////////////////////
1313
+
1314
+ var output;
1315
+
1316
+ if (source._id) {
1317
+ output = String(source._id);
1318
+ } else {
1319
+ output = String(source);
1320
+ }
1321
+
1322
+ var isValid = service.isValidID(output);
1323
+ if (!isValid) {
1324
+ return;
1325
+ }
1326
+
1327
+ return output;
1328
+ };
1329
+
1330
+ ///////////////////////////////////////////////////////////////////////////////
1331
+
1332
+ /**
1333
+ * Cleans and maps an array of objects to an array of IDs
1334
+ * @alias utils.ids
1335
+ * @param {Array} array An array of objects or object ids
1336
+ * @param {Boolean} asObjectID Whether or not to map the ids as Mongo ObjectIds
1337
+ * @return {Array} An array of Ids
1338
+ *
1339
+ * @example
1340
+ * //Returns ['5cb3d8b3a2219970e6f86927', '5cb3d8b3a2219970e6f86927', '5cb3d8b3a2219970e6f86927']
1341
+ * sdk.utils.ids([{_id:'5cb3d8b3a2219970e6f86927'}, {_id:'5cb3d8b3a2219970e6f86927'}, null, '5cb3d8b3a2219970e6f86927'])
1342
+ */
1343
+
1344
+ service.ids = function (array) {
1345
+ if (!array) {
1346
+ return [];
1347
+ }
1348
+
1349
+ /////////////////////////////////
1350
+
1351
+ var ids = Object.keys(
1352
+ array.reduce(function (set, entry) {
1353
+ if (!entry) {
1354
+ return set;
1355
+ }
1356
+
1357
+ var cleaned = service.id(entry);
1358
+
1359
+ if (cleaned) {
1360
+ set[cleaned] = 1;
1361
+ }
1362
+
1363
+ return set;
1364
+ }, {}),
1365
+ );
1366
+
1367
+ ///////////////////////////////
1368
+
1369
+ return ids;
1370
+ };
1371
+
1372
+ ///////////////////////////////////////////////////////////////////////////////
1373
+
1374
+ service.isValidID = function (input) {
1375
+ var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
1376
+ return checkForHexRegExp.test(String(input));
1377
+ };
1378
+
1379
+ ///////////////////////////////////////////////////////////////////////////////
1380
+
1381
+ /**
1382
+ * Helper function for retrieving a human readable error message from server error response objects
1383
+ * @alias utils.errorMessage
1384
+ * @param {Object} error The error object to translate
1385
+ * @return {String} The resulting human readable error message
1386
+ */
1387
+ service.errorMessage = function (err) {
1388
+ if (!err) {
1389
+ return;
1390
+ }
1391
+
1392
+ if (Array.isArray(err)) {
1393
+ err = err[0];
1394
+ }
1395
+
1396
+ // Walk through the error object to find the most useful message
1397
+ let message =
1398
+ err?.response?.data?.message ||
1399
+ (typeof err?.response?.data === "string" ? err.response.data : null) ||
1400
+ err?.message ||
1401
+ null;
1402
+
1403
+ if (Array.isArray(message)) {
1404
+ message = message[0];
1405
+ }
1406
+
1407
+ return message || JSON.stringify(err);
1408
+ };
1409
+
1410
+ ////////////////////////////////////
1411
+
1412
+ /**
1413
+ * Generates a globally unique ID, helpful for adding unique keys for iterable loops
1414
+ * @alias utils.guid
1415
+ * @return {String} The new globally unique identifier
1416
+ * @example
1417
+ * //Returns 4323a78br-z16h-289j-zwl1-938lda334asd
1418
+ * sdk.utils.guid()
1419
+ */
1420
+ service.guid = function () {
1421
+ if (typeof crypto !== "undefined" &amp;&amp; crypto.randomUUID) {
1422
+ return crypto.randomUUID();
1423
+ }
1424
+ // Fallback for environments without crypto.randomUUID
1425
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
1426
+ const r = (Math.random() * 16) | 0;
1427
+ return (c === "x" ? r : (r &amp; 0x3) | 0x8).toString(16);
1428
+ });
1429
+ };
1430
+
1431
+ ////////////////////////////////////
1432
+ ////////////////////////////////////
1433
+ ////////////////////////////////////
1434
+
1435
+ /**
1436
+ * Helper function for cleaning strings to use as database ids
1437
+ * @alias utils.machineName
1438
+ * @param {String} string The string to clean eg. (Awesome Event!)
1439
+ * @return {String} A cleaned and formatted string eg. (awesomeEvent)
1440
+ */
1441
+ service.machineName = function (string) {
1442
+ if (!string || !string.length) {
1443
+ return;
1444
+ }
1445
+
1446
+ var regexp = /[^a-zA-Z0-9-_]+/g;
1447
+ return String(string)
1448
+ .replace(regexp, " ")
1449
+ .split("_")
1450
+ .map((part) => _camelCase(part))
1451
+ .join("_");
1452
+ };
1453
+
1454
+ /////////////////////////////////////////////
1455
+ /////////////////////////////////////////////
1456
+ /////////////////////////////////////////////
1457
+
1458
+ export default service;
1459
+
1460
+ /////////////////////////////////////////////
1461
+
1462
+ /**
1463
+ * A lightweight event emitter that can be attached to any service object
1464
+ * to provide pub/sub event capabilities. Can be called with or without `new`.
1465
+ */
1466
+ export function EventDispatcher() {
1467
+ const handlers = new Map();
1468
+
1469
+ const emitter = {
1470
+ dispatch(event, details) {
1471
+ const fns = handlers.get(event);
1472
+ if (fns) {
1473
+ for (const fn of fns) {
1474
+ fn(details);
1475
+ }
1476
+ }
1477
+ },
1478
+
1479
+ addEventListener(event, callback) {
1480
+ if (typeof callback !== "function") {
1481
+ throw new TypeError(
1482
+ `Expected a function for addEventListener, received ${typeof callback}`,
1483
+ );
1484
+ }
1485
+
1486
+ if (!handlers.has(event)) {
1487
+ handlers.set(event, new Set());
1488
+ }
1489
+
1490
+ handlers.get(event).add(callback);
1491
+ },
1492
+
1493
+ removeEventListener(event, callback) {
1494
+ const fns = handlers.get(event);
1495
+ if (fns) {
1496
+ fns.delete(callback);
1497
+ if (fns.size === 0) {
1498
+ handlers.delete(event);
1499
+ }
1500
+ }
1501
+ },
1502
+
1503
+ removeAllListeners() {
1504
+ handlers.clear();
1505
+ },
1506
+
1507
+ bootstrap(target) {
1508
+ if (!target) return;
1509
+ target.dispatch = emitter.dispatch;
1510
+ target.addEventListener = emitter.addEventListener;
1511
+ target.removeEventListener = emitter.removeEventListener;
1512
+ target.removeAllListeners = emitter.removeAllListeners;
1513
+ },
1514
+ };
1515
+
1516
+ return emitter;
1517
+ }
1518
+ </code></pre>
1519
+ </article>
1520
+ </section>
1521
+
1522
+
1523
+
1524
+
1525
+
1526
+
1527
+ </div>
1528
+
1529
+ <br class="clear">
1530
+
1531
+ <footer>
1532
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.11</a> on Mon Jun 01 2026 23:37:17 GMT+1000 (Australian Eastern Standard Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1533
+ </footer>
1534
+
1535
+ <script>prettyPrint();</script>
1536
+ <script src="scripts/polyfill.js"></script>
1537
+ <script src="scripts/linenumber.js"></script>
1538
+
1539
+
1540
+
1541
+ </body>
1542
+ </html>