@getjoystick/joystick-js
Advanced tools
Comparing version 0.1.2 to 0.1.3-alpha.1
'use strict'; | ||
var J = require('axios'); | ||
var webcrypto = require('@peculiar/webcrypto'); | ||
var F = require('crypto-js/sha256'); | ||
@@ -9,6 +9,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } | ||
var J__default = /*#__PURE__*/_interopDefault(J); | ||
var F__default = /*#__PURE__*/_interopDefault(F); | ||
var S=Object.defineProperty,T=Object.defineProperties;var O=Object.getOwnPropertyDescriptors;var k=Object.getOwnPropertySymbols;var M=Object.prototype.hasOwnProperty,L=Object.prototype.propertyIsEnumerable;var b=(i,e,t)=>e in i?S(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t,c=(i,e)=>{for(var t in e||(e={}))M.call(e,t)&&b(i,t,e[t]);if(k)for(var t of k(e))L.call(e,t)&&b(i,t,e[t]);return i},l=(i,e)=>T(i,O(e));var a=class extends Error{constructor(e){super(e);}};var p=class extends a{constructor(e){super(e);}};var m=class extends p{constructor(e){super(e);}};var d=class extends p{constructor(e){super(e);}};var h=class extends p{constructor(e){super(e);}};var o=class extends a{constructor(e){super(e);}};var v=class{constructor(e,t){this.validateApiKey(e),this.logger=t,this.client=J__default.default.create({headers:{Accept:"application/json","Content-Type":"application/json","x-api-key":e},responseEncoding:"UTF-8",responseType:"json",validateStatus:r=>r===200});}validateApiKey(e){if(!e||!e.trim())throw new o(`Invalid apiKey: <${e}>`)}async put(e,t,r){this.logger.debug("Sending put request",{url:e,payload:t,params:r});try{await this.client.put(e,t,{params:r});}catch(n){throw this.checkForErrors(n),n}}async post(e,t,r){this.logger.debug("Sending post request",{url:e,payload:t,params:r});try{let{data:n}=await this.client.post(e,t,{params:r});return n}catch(n){throw this.checkForErrors(n),n}}checkForErrors(e){var t;if(e instanceof J.AxiosError&&((t=e.response)!=null&&t.status)){let{status:r}=e.response;if(r>=400&&r<500)throw new h(e.message);if(r>=500)throw new d(e.message);if(r!=200)throw new m(e.message)}}};var x=class{constructor(e,t,r=1e3,n=Date.now){this.validateCacheExpirationSeconds(e),this.validateMaxItemsInCache(r),this.cacheExpirationMs=e*1e3,this.logger=t,this.maxItemsInCache=r,this.nowFn=n,this.cache=new Map;}setCacheExpirationSeconds(e){this.validateCacheExpirationSeconds(e),this.cacheExpirationMs=e*1e3;}getCacheSize(){return this.cache.size}set(e,t){return this.cache.set(e,{value:t,cachedAtTimestampMs:this.nowFn(),lastAccessedAtTimestampMs:this.nowFn()}),this.checkLruMaxSize(),Promise.resolve()}get(e){let t=this.cache.get(e);return !t||this.isExpired(t)?Promise.resolve(void 0):(t.lastAccessedAtTimestampMs=this.nowFn(),Promise.resolve(t.value))}isExpired({cachedAtTimestampMs:e}){return e+this.cacheExpirationMs<this.nowFn()}async clear(){await this.cache.clear();}checkLruMaxSize(){if(this.cache.size<=this.maxItemsInCache)return;let e=[...this.cache.entries()].sort(([,t],[,r])=>r.lastAccessedAtTimestampMs-t.lastAccessedAtTimestampMs).slice(this.maxItemsInCache).map(([t])=>t);this.logger.debug({keysToDelete:e},"checkLruMaxSize"),e.forEach(t=>this.cache.delete(t));}validateCacheExpirationSeconds(e){if(e<0)throw new o(`Invalid cacheExpirationSeconds: <${e}>. It should be equal or greater than 0`)}validateMaxItemsInCache(e){if(e<1)throw new o(`Invalid maxItemsInCache: <${e}>. It should be greater than 0`)}};var A=class{debug(...e){this.shouldLog("debug")&&console.debug(...e);}error(...e){this.shouldLog("error")&&console.error(...e);}info(...e){this.shouldLog("info")&&console.info(...e);}warn(...e){this.shouldLog("warn")&&console.warn(...e);}shouldLog(e){switch(e){case"info":case"error":case"warn":return !0;case"debug":return process.env.NODE_ENV==="development"}}};var F=new webcrypto.Crypto,V=i=>Array.from(new Uint8Array(i)).map(e=>e.toString(16).padStart(2,"0")).join("");async function E(i){let e=typeof i=="string"?i:JSON.stringify(i),t=await F.subtle.digest("SHA-256",new TextEncoder().encode(e));return V(t)}var y=class extends a{constructor(e){super(e);}};var g=class extends y{constructor(e){super(e);}};var R=class{constructor(e,t){this.client=e,this.logger=t;}async getDynamicContent(e,t,r){let{params:n,semVer:s,userId:u=""}=t,f=await this.client.post("https://api.getjoystick.com/api/v1/combine/",{u,v:s,p:n},{c:JSON.stringify(e),dynamic:"true",responseType:r});return this.checkForErrors(f),Object.entries(f).reduce((C,[w,P])=>l(c({},C),{[w]:P}),{})}async publishContentUpdate(e,t){let{description:r,content:n,dynamicContentMap:s=[]}=t;this.validateDescription(r),this.validateContent(n),this.validateDynamicContentMap(s),await this.client.put(`https://capi.getjoystick.com/api/v1/config/${e}`,{d:r,c:n,m:s});}validateDescription(e){if(!e||e.length<1||e.length>50)throw new o(`Invalid description: ${e}. It should be between 1 and 50 characters long`)}validateContent(e){try{JSON.stringify(e);}catch(t){throw new o("Invalid content. It should be JSON encodable")}}validateDynamicContentMap(e){if(e)try{JSON.stringify(e);}catch(t){throw new o("Invalid dynamicContentMap. It should be JSON encodable")}}checkForErrors(e){let t=Object.values(e).filter(r=>typeof r=="string").map(r=>`- ${r}`);if(t.length>0)throw new g(t.join(` | ||
`))}};var K=300,D=/^\d+.\d+.\d+$/,I=class{constructor(e,t){var f,C,w;let{semVer:r,userId:n,apiKey:s,options:u}=e;this.validateApiKey(s),this.validateUserId(n),this.validateSemVer(r),this.validateCacheExpirationSeconds(u==null?void 0:u.cacheExpirationSeconds),this.properties=e,this.logger=(f=t==null?void 0:t.logger)!=null?f:new A,this.apiClient=(C=t==null?void 0:t.apiClient)!=null?C:new R(new v(this.getApiKey(),this.logger),this.logger),this.cache=(w=t==null?void 0:t.cache)!=null?w:new x(this.getCacheExpirationSeconds(),this.logger);}getCache(){return this.cache}getParamValue(e){var t;return (t=this.properties.params)==null?void 0:t[e]}setParamValue(e,t){return this.properties.params=l(c({},this.properties.params),{[e]:t}),this}getApiKey(){return this.properties.apiKey}getUserId(){return this.properties.userId}getSemVer(){return this.properties.semVer}setSemVer(e){return this.validateSemVer(e),this.properties.semVer=e,this}getParams(){var e;return (e=this.properties.params)!=null?e:{}}getCacheExpirationSeconds(){var e,t;return (t=(e=this.properties.options)==null?void 0:e.cacheExpirationSeconds)!=null?t:K}async publishContentUpdate(e,t){this.validateContentId(e);try{return await this.apiClient.publishContentUpdate(e,t)}catch(r){throw r instanceof m?this.logger.error("Found an unknown error when publishing content update to Joystick"):r instanceof d?this.logger.error("Found a server error when publishing content update to Joystick"):r instanceof h&&this.logger.error("Found a client error when publishing content update to Joystick"),r}}async clearCache(){await this.cache.clear();}async getContent(e,t){return (await this.getContents([e],t))[e]}async getContents(e,t){this.validateContentIds(e);let r=await this.buildCacheKey(e,t),n=t!=null&&t.refresh?void 0:await this.cache.get(r);if(!n)try{n=await this.apiClient.getDynamicContent(e,{params:this.getParams(),semVer:this.getSemVer(),userId:this.getUserId()},this.getSerialized(t==null?void 0:t.serialized)?"serialized":void 0),await this.cache.set(r,n);}catch(s){throw s instanceof m?this.logger.error("Found an unknown error when getting content from Joystick"):s instanceof g?this.logger.error(`The following errors found when calling Multiple Content API: | ||
${s.message}`):s instanceof d?this.logger.error("Found a server error when getting content from Joystick"):s instanceof h&&this.logger.error("Found a client error when getting content from Joystick"),s}return t!=null&&t.fullResponse?n:this.simplifyResponse(n)}setUserId(e){return this.validateUserId(e),this.properties.userId=e,this}setSerialized(e){return this.properties.options=l(c({},this.properties.options),{serialized:e}),this}setCacheExpirationSeconds(e){return this.validateCacheExpirationSeconds(e),this.properties.options=l(c({},this.properties.options),{cacheExpirationSeconds:e}),this.cache.setCacheExpirationSeconds(e),this}setParams(e){return this.properties.params=e,this}getSerialized(e){var t;return e!=null?e:(t=this.properties.options)==null?void 0:t.serialized}simplifyResponse(e){return Object.entries(e).reduce((t,[r,n])=>l(c({},t),{[r]:n.data}),{})}async buildCacheKey(e,t){var n;let r=[this.getApiKey(),this.getParamsSortedByKeyAsc(this.getParams()),this.getSemVer(),this.getUserId(),[...e].sort(),this.getSerialized(t==null?void 0:t.serialized),(n=t==null?void 0:t.fullResponse)!=null?n:!1];return await E(r)}getParamsSortedByKeyAsc(e={}){return Object.entries(e).sort(([t],[r])=>t.localeCompare(r)).reduce((t,[r,n])=>l(c({},t),{[r]:n}),{})}validateContentIds(e){if(!e||e.length==0||e.some(t=>!t.trim()))throw new o("The contentIds parameter must be a non-empty array of strings")}validateApiKey(e){if(!e||!e.trim())throw new o(`Invalid apiKey: <${e}>`)}validateCacheExpirationSeconds(e){if(e!=null&&e<0)throw new o(`Invalid cacheExpirationSeconds: <${e}>`)}validateSemVer(e){if(e&&!D.test(e))throw new o(`Invalid semVer: <${e}>`)}validateUserId(e){if(e&&!e.trim())throw new o(`Invalid userId: <${e}>`)}validateContentId(e){if(!e||!e.trim())throw new o(`Invalid contentId: <${e}>`)}}; | ||
var T=Object.defineProperty,S=Object.defineProperties;var O=Object.getOwnPropertyDescriptors;var k=Object.getOwnPropertySymbols;var M=Object.prototype.hasOwnProperty,L=Object.prototype.propertyIsEnumerable;var b=(i,e,t)=>e in i?T(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t,c=(i,e)=>{for(var t in e||(e={}))M.call(e,t)&&b(i,t,e[t]);if(k)for(var t of k(e))L.call(e,t)&&b(i,t,e[t]);return i},l=(i,e)=>S(i,O(e));var a=class extends Error{constructor(e){super(e);}};var p=class extends a{constructor(e){super(e);}};var m=class extends p{constructor(e){super(e);}};var d=class extends p{constructor(e){super(e);}};var h=class extends p{constructor(e){super(e);}};var s=class extends a{constructor(e){super(e);}};var v=class{constructor(e,t){this.validateApiKey(e),this.logger=t,this.client=J__default.default.create({headers:{Accept:"application/json","Content-Type":"application/json","x-api-key":e},responseEncoding:"UTF-8",responseType:"json",validateStatus:r=>r===200});}validateApiKey(e){if(!e||!e.trim())throw new s(`Invalid apiKey: <${e}>`)}async put(e,t,r){this.logger.debug("Sending put request",{url:e,payload:t,params:r});try{await this.client.put(e,t,{params:r});}catch(n){throw this.checkForErrors(n),n}}async post(e,t,r){this.logger.debug("Sending post request",{url:e,payload:t,params:r});try{let{data:n}=await this.client.post(e,t,{params:r});return n}catch(n){throw this.checkForErrors(n),n}}checkForErrors(e){var t;if(e instanceof J.AxiosError&&((t=e.response)!=null&&t.status)){let{status:r}=e.response;if(r>=400&&r<500)throw new h(e.message);if(r>=500)throw new d(e.message);if(r!=200)throw new m(e.message)}}};var x=class{constructor(e,t,r=1e3,n=Date.now){this.validateCacheExpirationSeconds(e),this.validateMaxItemsInCache(r),this.cacheExpirationMs=e*1e3,this.logger=t,this.maxItemsInCache=r,this.nowFn=n,this.cache=new Map;}setCacheExpirationSeconds(e){this.validateCacheExpirationSeconds(e),this.cacheExpirationMs=e*1e3;}getCacheSize(){return this.cache.size}set(e,t){return this.cache.set(e,{value:t,cachedAtTimestampMs:this.nowFn(),lastAccessedAtTimestampMs:this.nowFn()}),this.checkLruMaxSize(),Promise.resolve()}get(e){let t=this.cache.get(e);return !t||this.isExpired(t)?Promise.resolve(void 0):(t.lastAccessedAtTimestampMs=this.nowFn(),Promise.resolve(t.value))}isExpired({cachedAtTimestampMs:e}){return e+this.cacheExpirationMs<this.nowFn()}async clear(){await this.cache.clear();}checkLruMaxSize(){if(this.cache.size<=this.maxItemsInCache)return;let e=[...this.cache.entries()].sort(([,t],[,r])=>r.lastAccessedAtTimestampMs-t.lastAccessedAtTimestampMs).slice(this.maxItemsInCache).map(([t])=>t);this.logger.debug({keysToDelete:e},"checkLruMaxSize"),e.forEach(t=>this.cache.delete(t));}validateCacheExpirationSeconds(e){if(e<0)throw new s(`Invalid cacheExpirationSeconds: <${e}>. It should be equal or greater than 0`)}validateMaxItemsInCache(e){if(e<1)throw new s(`Invalid maxItemsInCache: <${e}>. It should be greater than 0`)}};var R=class{debug(...e){this.shouldLog("debug")&&console.debug(...e);}error(...e){this.shouldLog("error")&&console.error(...e);}info(...e){this.shouldLog("info")&&console.info(...e);}warn(...e){this.shouldLog("warn")&&console.warn(...e);}shouldLog(e){switch(e){case"info":case"error":case"warn":return !0;case"debug":return process.env.NODE_ENV==="development"}}};async function P(i){let e=typeof i=="string"?i:JSON.stringify(i);return F__default.default(e).toString()}var y=class extends a{constructor(e){super(e);}};var g=class extends y{constructor(e){super(e);}};var A=class{constructor(e,t){this.client=e,this.logger=t;}async getDynamicContent(e,t,r){let{params:n,semVer:o,userId:u=""}=t,f=await this.client.post("https://api.getjoystick.com/api/v1/combine/",{u,v:o,p:n},{c:JSON.stringify(e),dynamic:"true",responseType:r});return this.checkForErrors(f),Object.entries(f).reduce((C,[w,E])=>l(c({},C),{[w]:E}),{})}async publishContentUpdate(e,t){let{description:r,content:n,dynamicContentMap:o=[]}=t;this.validateDescription(r),this.validateContent(n),this.validateDynamicContentMap(o),await this.client.put(`https://capi.getjoystick.com/api/v1/config/${e}`,{d:r,c:n,m:o});}validateDescription(e){if(!e||e.length<1||e.length>50)throw new s(`Invalid description: ${e}. It should be between 1 and 50 characters long`)}validateContent(e){try{JSON.stringify(e);}catch(t){throw new s("Invalid content. It should be JSON encodable")}}validateDynamicContentMap(e){if(e)try{JSON.stringify(e);}catch(t){throw new s("Invalid dynamicContentMap. It should be JSON encodable")}}checkForErrors(e){let t=Object.values(e).filter(r=>typeof r=="string").map(r=>`- ${r}`);if(t.length>0)throw new g(t.join(` | ||
`))}};var U=300,V=/^\d+.\d+.\d+$/,I=class{constructor(e,t){var f,C,w;let{semVer:r,userId:n,apiKey:o,options:u}=e;this.validateApiKey(o),this.validateUserId(n),this.validateSemVer(r),this.validateCacheExpirationSeconds(u==null?void 0:u.cacheExpirationSeconds),this.properties=e,this.logger=(f=t==null?void 0:t.logger)!=null?f:new R,this.apiClient=(C=t==null?void 0:t.apiClient)!=null?C:new A(new v(this.getApiKey(),this.logger),this.logger),this.cache=(w=t==null?void 0:t.cache)!=null?w:new x(this.getCacheExpirationSeconds(),this.logger);}getCache(){return this.cache}getParamValue(e){var t;return (t=this.properties.params)==null?void 0:t[e]}setParamValue(e,t){return this.properties.params=l(c({},this.properties.params),{[e]:t}),this}getApiKey(){return this.properties.apiKey}getUserId(){return this.properties.userId}getSemVer(){return this.properties.semVer}setSemVer(e){return this.validateSemVer(e),this.properties.semVer=e,this}getParams(){var e;return (e=this.properties.params)!=null?e:{}}getCacheExpirationSeconds(){var e,t;return (t=(e=this.properties.options)==null?void 0:e.cacheExpirationSeconds)!=null?t:U}async publishContentUpdate(e,t){this.validateContentId(e);try{return await this.apiClient.publishContentUpdate(e,t)}catch(r){throw r instanceof m?this.logger.error("Found an unknown error when publishing content update to Joystick"):r instanceof d?this.logger.error("Found a server error when publishing content update to Joystick"):r instanceof h&&this.logger.error("Found a client error when publishing content update to Joystick"),r}}async clearCache(){await this.cache.clear();}async getContent(e,t){return (await this.getContents([e],t))[e]}async getContents(e,t){this.validateContentIds(e);let r=await this.buildCacheKey(e,t),n=t!=null&&t.refresh?void 0:await this.cache.get(r);if(!n)try{n=await this.apiClient.getDynamicContent(e,{params:this.getParams(),semVer:this.getSemVer(),userId:this.getUserId()},this.getSerialized(t==null?void 0:t.serialized)?"serialized":void 0),await this.cache.set(r,n);}catch(o){throw o instanceof m?this.logger.error("Found an unknown error when getting content from Joystick"):o instanceof g?this.logger.error(`The following errors found when calling Multiple Content API: | ||
${o.message}`):o instanceof d?this.logger.error("Found a server error when getting content from Joystick"):o instanceof h&&this.logger.error("Found a client error when getting content from Joystick"),o}return t!=null&&t.fullResponse?n:this.simplifyResponse(n)}setUserId(e){return this.validateUserId(e),this.properties.userId=e,this}setSerialized(e){return this.properties.options=l(c({},this.properties.options),{serialized:e}),this}setCacheExpirationSeconds(e){return this.validateCacheExpirationSeconds(e),this.properties.options=l(c({},this.properties.options),{cacheExpirationSeconds:e}),this.cache.setCacheExpirationSeconds(e),this}setParams(e){return this.properties.params=e,this}getSerialized(e){var t;return e!=null?e:(t=this.properties.options)==null?void 0:t.serialized}simplifyResponse(e){return Object.entries(e).reduce((t,[r,n])=>l(c({},t),{[r]:n.data}),{})}async buildCacheKey(e,t){var n;let r=[this.getApiKey(),this.getParamsSortedByKeyAsc(this.getParams()),this.getSemVer(),this.getUserId(),[...e].sort(),this.getSerialized(t==null?void 0:t.serialized),(n=t==null?void 0:t.fullResponse)!=null?n:!1];return await P(r)}getParamsSortedByKeyAsc(e={}){return Object.entries(e).sort(([t],[r])=>t.localeCompare(r)).reduce((t,[r,n])=>l(c({},t),{[r]:n}),{})}validateContentIds(e){if(!e||e.length==0||e.some(t=>!t.trim()))throw new s("The contentIds parameter must be a non-empty array of strings")}validateApiKey(e){if(!e||!e.trim())throw new s(`Invalid apiKey: <${e}>`)}validateCacheExpirationSeconds(e){if(e!=null&&e<0)throw new s(`Invalid cacheExpirationSeconds: <${e}>`)}validateSemVer(e){if(e&&!V.test(e))throw new s(`Invalid semVer: <${e}>`)}validateUserId(e){if(e&&!e.trim())throw new s(`Invalid userId: <${e}>`)}validateContentId(e){if(!e||!e.trim())throw new s(`Invalid contentId: <${e}>`)}}; | ||
@@ -19,3 +20,3 @@ exports.ApiBadRequestError = h; | ||
exports.ApiServerError = d; | ||
exports.InvalidArgumentError = o; | ||
exports.InvalidArgumentError = s; | ||
exports.Joystick = I; | ||
@@ -22,0 +23,0 @@ exports.JoystickError = a; |
{ | ||
"name": "@getjoystick/joystick-js", | ||
"version": "0.1.2", | ||
"version": "0.1.3-alpha.1", | ||
"description": "Javascript SDK for Joystick", | ||
@@ -21,2 +21,3 @@ "main": "./dist/index.js", | ||
"devDependencies": { | ||
"@types/crypto-js": "^4.1.1", | ||
"@types/jest": "^29.4.0", | ||
@@ -51,4 +52,4 @@ "@typescript-eslint/eslint-plugin": "^5.58.0", | ||
"dependencies": { | ||
"@peculiar/webcrypto": "^1.4.3", | ||
"axios": "^1.3.4" | ||
"axios": "^1.3.4", | ||
"crypto-js": "^4.1.1" | ||
}, | ||
@@ -55,0 +56,0 @@ "repository": { |
@@ -8,8 +8,6 @@ # Javascript Client for [Joystick Remote Config](https://www.getjoystick.com/) | ||
Use Joystick to manage and use JSON remote configs easily with any Javascript/Typescript projects. Get configurations out of your code base. Update your configurations instantly without a long build, deploy process. | ||
Streamline your app or game development process with Joystick's Javascript/Typescript JSON remote config platform. Easily manage and update configurations without codebase clutter or lengthy deployment processes. Our modern platform offers advanced workflow management, automated version control, and seamless integration with any Javascript or Typescript project. Plus, our native multi-environment support with permissions and review workflow ensures smooth operations your entire team will love. | ||
Joystick is a modern remote config platform built for to manage configurations effortless in one place, behind one API. We are natively multi-environment, have automated version control with advanced work-flow & permissions management, and much more. Your entire team will love us. | ||
Experience the benefits of simplified configuration management with Joystick. Try our @getjoystick/joystick-js library today to see how easy it is to my your app or game dynamic and fundamentally upgrade your team's workflow. | ||
The @getjoystick/joystick-js library simplifies how your Javascript/Typescript project can communicate with the Joystick API to get remote configs over a REST API. | ||
- [Full Developer Documentation](https://docs.getjoystick.com) | ||
@@ -16,0 +14,0 @@ - [Joystick Remote Config](https://getjoystick.com) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
0
120256
15
416
203
+ Addedcrypto-js@^4.1.1
+ Addedcrypto-js@4.2.0(transitive)
- Removed@peculiar/webcrypto@^1.4.3
- Removed@peculiar/asn1-schema@2.3.13(transitive)
- Removed@peculiar/json-schema@1.1.12(transitive)
- Removed@peculiar/webcrypto@1.5.0(transitive)
- Removedasn1js@3.0.5(transitive)
- Removedpvtsutils@1.3.6(transitive)
- Removedpvutils@1.1.3(transitive)
- Removedtslib@2.8.1(transitive)
- Removedwebcrypto-core@1.8.1(transitive)