@webority/mobile-core 0.16.4 → 0.16.5

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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retryAfterMs=exports.isRetryableStatus=exports.isRetryableFailure=exports.isNeverSentError=exports.attachRetry=exports.IDEMPOTENCY_KEY_HEADER=void 0;var _axios=_interopRequireDefault(require("axios")),_index=require("../config/index.js"),_workspace=require("./workspace.js");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const IDEMPOTENCY_KEY_HEADER=exports.IDEMPOTENCY_KEY_HEADER="Idempotency-Key",isRetryableStatus=e=>"number"==typeof e&&(429===e||e>=500&&e<=599);exports.isRetryableStatus=isRetryableStatus;const IDEMPOTENT_METHODS=new Set(["get","head","options","put","delete"]),NEVER_SENT_CODES=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","ENETUNREACH","EHOSTUNREACH"]),isNeverSentError=e=>!e.response&&"string"==typeof e.code&&NEVER_SENT_CODES.has(e.code);exports.isNeverSentError=isNeverSentError;const MAX_RETRY_AFTER_MS=3e4,retryAfterMs=e=>{const r=e.response;if(!r)return null;const t=r.data,s=r.headers,o="function"==typeof s?.get?s.get("retry-after"):s?.["retry-after"];for(const e of[t?.retryAfterSeconds,o]){const r=Number(e);if(null!=e&&Number.isFinite(r)&&r>0)return 1e3*r}return null};exports.retryAfterMs=retryAfterMs;const hasIdempotencyKey=e=>{const r=e?.headers,t="function"==typeof r?.get?r.get(IDEMPOTENCY_KEY_HEADER):r?.[IDEMPOTENCY_KEY_HEADER];return"string"==typeof t&&""!==t},isRetryableFailure=e=>{if(_axios.default.isCancel(e)||"ERR_CANCELED"===e.code)return!1;if(isNeverSentError(e))return!0;const r=(e.config?.method??"get").toLowerCase(),t=IDEMPOTENT_METHODS.has(r),s=e.response?.status;if(void 0===s)return t;if(!isRetryableStatus(s))return!1;const o=retryAfterMs(e);return!(null!==o&&o>3e4)&&(t||(429===s||503===s)&&hasIdempotencyKey(e.config))};exports.isRetryableFailure=isRetryableFailure;const DEFAULT_POLICY={retryDelayMs:e=>e<=1?0:2**e*1e3,shouldRetry:isRetryableFailure,onRetry:()=>{}},waitOrAbort=(e,r)=>new Promise(t=>{const onAbort=()=>{clearTimeout(s),t(!1)},s=setTimeout(()=>{r?.removeEventListener?.("abort",onAbort),t(!0)},e);r?.addEventListener?.("abort",onAbort,{once:!0})}),attachRetry=(e,r={})=>{e.interceptors.response.use(void 0,async t=>{const s=t,o=s?.config;if(!o||!1===o.retry||(0,_workspace.isWorkspaceChangedResponse)(s))return Promise.reject(t);const n="object"==typeof o.retry?o.retry:{},i={...DEFAULT_POLICY,retries:(0,_index.getConfigValue)("retries"),...r,...n},a=(o.__retryAttempt??0)+1;if(a>i.retries||!i.shouldRetry(s))return Promise.reject(t);if(o.signal?.aborted)return Promise.reject(t);o.__retryAttempt=a,o.transformRequest=[e=>e],i.onRetry(a,s);const E=retryAfterMs(s)??i.retryDelayMs(a);return await waitOrAbort(E,o.signal)?e.request(o):Promise.reject(t)})};exports.attachRetry=attachRetry;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retryAfterMs=exports.isRetryableStatus=exports.isRetryableFailure=exports.isNeverSentError=exports.attachRetry=exports.IDEMPOTENCY_KEY_HEADER=void 0;var _axios=_interopRequireDefault(require("axios")),_index=require("../config/index.js"),_workspace=require("./workspace.js");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const IDEMPOTENCY_KEY_HEADER=exports.IDEMPOTENCY_KEY_HEADER="Idempotency-Key",isRetryableStatus=e=>"number"==typeof e&&(429===e||e>=500&&e<=599);exports.isRetryableStatus=isRetryableStatus;const IDEMPOTENT_METHODS=new Set(["get","head","options","put","delete"]),NEVER_SENT_CODES=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","ENETUNREACH","EHOSTUNREACH"]),isNeverSentError=e=>!e.response&&"string"==typeof e.code&&NEVER_SENT_CODES.has(e.code);exports.isNeverSentError=isNeverSentError;const MAX_RETRY_AFTER_MS=3e4,retryAfterMs=e=>{const t=e.response;if(!t)return null;const r=t.data,s=t.headers,o="function"==typeof s?.get?s.get("retry-after"):s?.["retry-after"];for(const e of[r?.retryAfterSeconds,o]){const t=Number(e);if(null!=e&&Number.isFinite(t)&&t>0)return 1e3*t}return null};exports.retryAfterMs=retryAfterMs;const hasIdempotencyKey=e=>{const t=e?.headers,r="function"==typeof t?.get?t.get(IDEMPOTENCY_KEY_HEADER):t?.[IDEMPOTENCY_KEY_HEADER];return"string"==typeof r&&""!==r},isRetryableFailure=e=>{if(_axios.default.isCancel(e)||"ERR_CANCELED"===e.code)return!1;if(isNeverSentError(e))return!0;const t=(e.config?.method??"get").toLowerCase(),r=IDEMPOTENT_METHODS.has(t),s=e.response?.status;if(void 0===s)return r;if(!isRetryableStatus(s))return!1;const o=retryAfterMs(e);return!(null!==o&&o>3e4)&&(r||(429===s||503===s)&&hasIdempotencyKey(e.config))};exports.isRetryableFailure=isRetryableFailure;const DEFAULT_POLICY={retryDelayMs:e=>Math.random()*Math.min(2e3,500*2**(e-1)),shouldRetry:isRetryableFailure,onRetry:()=>{}},waitOrAbort=(e,t)=>new Promise(r=>{const onAbort=()=>{clearTimeout(s),r(!1)},s=setTimeout(()=>{t?.removeEventListener?.("abort",onAbort),r(!0)},e);t?.addEventListener?.("abort",onAbort,{once:!0})}),attachRetry=(e,t={})=>{e.interceptors.response.use(void 0,async r=>{const s=r,o=s?.config;if(!o||!1===o.retry||(0,_workspace.isWorkspaceChangedResponse)(s))return Promise.reject(r);const n="object"==typeof o.retry?o.retry:{},i={...DEFAULT_POLICY,retries:(0,_index.getConfigValue)("retries"),...t,...n},a=(o.__retryAttempt??0)+1;if(a>i.retries||!i.shouldRetry(s))return Promise.reject(r);if(o.signal?.aborted)return Promise.reject(r);o.__retryAttempt=a,1===a&&(o.__retryStartedAt=Date.now()),o.transformRequest=[e=>e];const E=retryAfterMs(s)??i.retryDelayMs(a),u=o.__retryStartedAt??Date.now();if(Date.now()-u+E>2e4)return Promise.reject(r);i.onRetry(a,s);return await waitOrAbort(E,o.signal)?e.request(o):Promise.reject(r)})};exports.attachRetry=attachRetry;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.setRemoteLogger=exports.setDeviceContext=exports.getDeviceContext=exports.configureLogger=exports.Logger=void 0;var _index=require("../config/index.js"),_extractApiError=require("../errors/extractApiError.js"),_redact=require("./redact.js");const Colors={RESET:"",GRAY:"",BLUE:"",YELLOW:"",RED_BOLD:""},LogLevels={DEBUG:{level:"debug",color:Colors.GRAY},INFO:{level:"info",color:Colors.BLUE},WARN:{level:"warn",color:Colors.YELLOW},ERROR:{level:"error",color:Colors.RED_BOLD}},isLogLevelAllowed=e=>{const r=["debug","info","warn","error"],o=(0,_index.getConfigValue)("logLevel","info");return r.indexOf(e)>=r.indexOf(o)},isEnabled=()=>(0,_index.getConfigValue)("loggingEnabled",!0);let remote=null;const setRemoteLogger=e=>{remote=e};exports.setRemoteLogger=setRemoteLogger;const safe=e=>{if(e)try{e()}catch{}};let deviceContext=null;const normalizeAttributeValue=e=>null==e?null:"string"==typeof e||"number"==typeof e||"boolean"==typeof e?e:String(e),setDeviceContext=e=>{if(deviceContext=e,e)for(const[r,o]of Object.entries(e))safe(()=>remote?.setAttribute?.(r,normalizeAttributeValue(o)))};exports.setDeviceContext=setDeviceContext;const getDeviceContext=()=>deviceContext;exports.getDeviceContext=getDeviceContext;const DEFAULT_LOGGER_OPTIONS={dedupeWindowMs:5e3,dedupeMaxPerWindow:1,screenHistoryLimit:20,breadcrumbLimit:50};let loggerOptions={...DEFAULT_LOGGER_OPTIONS};const configureLogger=e=>{const{redactKeys:r,...o}=e;void 0!==r&&(0,_redact.configureRedaction)(r),loggerOptions={...loggerOptions,...o},screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit)),trimBreadcrumbs()};exports.configureLogger=configureLogger;let currentScreen=null,screenHistory=[];const breadcrumbs=[],trimBreadcrumbs=()=>{const e=breadcrumbs.length-loggerOptions.breadcrumbLimit;e>0&&breadcrumbs.splice(0,e)},dedupeMap=new Map,MAX_DEDUPE_ENTRIES=200,dedupeKeyFor=e=>{const r=e.stack?.split("\n")[1]?.trim();return r?`${e.message}::${r}`:e.message},capDedupeMap=()=>{for(;dedupeMap.size>200;){const e=dedupeMap.keys().next().value;if(void 0===e)return;dedupeMap.delete(e)}},shouldForward=e=>{if(loggerOptions.dedupeWindowMs<=0)return{forward:!0};const r=Date.now(),o=dedupeMap.get(e);if(!o||r-o.windowStart>=loggerOptions.dedupeWindowMs){const t=o?.suppressedCount??0;return dedupeMap.set(e,{windowStart:r,count:1,suppressedCount:0}),capDedupeMap(),t>0?{forward:!0,suppressedCount:t}:{forward:!0}}return o.count+=1,o.count>loggerOptions.dedupeMaxPerWindow?(o.suppressedCount+=1,{forward:!1}):{forward:!0}},buildErrorContext=(e,r)=>{const o={...deviceContext};return null!==currentScreen&&(o.screen=currentScreen),r&&(o.suppressedCount=r),{...o,...e}},forwardErrorToRemote=(e,r)=>{const o=dedupeKeyFor(e),{forward:t,suppressedCount:s}=shouldForward(o);t&&safe(()=>remote?.recordError?.(e,buildErrorContext(r,s)))},logDebug=(e,...r)=>{isEnabled()&&isLogLevelAllowed(LogLevels.DEBUG.level)&&console.debug(`${LogLevels.DEBUG.color}[DEBUG]: ${(0,_redact.redactString)(e)}${Colors.RESET}`,...(0,_redact.redact)(r))},logInfo=(e,...r)=>{const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);isEnabled()&&isLogLevelAllowed(LogLevels.INFO.level)&&(console.info(`${LogLevels.INFO.color}[INFO]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("info",o,t)))},logWarning=(e,...r)=>{const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);isEnabled()&&isLogLevelAllowed(LogLevels.WARN.level)&&(console.warn(`${LogLevels.WARN.color}[WARNING]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("warn",o,t)))},logError=(e,...r)=>{const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("error",o,t));const s=r[0];void 0===s||(0,_extractApiError.isNoResponse)(s)||forwardErrorToRemote((0,_redact.redactError)(s),{source:"Logger.error",message:o})},breadcrumb=(e,r)=>{const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);breadcrumbs.push({message:o,data:t,timestampUtc:(new Date).toISOString()}),trimBreadcrumbs(),isEnabled()&&isLogLevelAllowed("info")&&console.info(`${Colors.BLUE}[BREADCRUMB]: ${o}${Colors.RESET}`,t??""),safe(()=>remote?.breadcrumb?.(o,t))},recordError=(e,r)=>{const o=(0,_redact.redactError)(e),t=(0,_redact.redact)(r);(0,_extractApiError.isNoResponse)(e)?logInfo(`No response: ${o.message}`):(isEnabled()&&isLogLevelAllowed("error")&&console.error(`${Colors.RED_BOLD}[RECORDED]: ${o.message}${Colors.RESET}`,t??""),forwardErrorToRemote(o,t))},asDict=e=>"object"==typeof e&&null!==e?e:null,headerValue=(e,r)=>{const o=asDict(e);if(!o)return null;const t="function"==typeof o.get?o.get.call(e,r):o[r]??o[r.toLowerCase()];return"string"==typeof t&&""!==t?t:null},requestFailed=(e,r={})=>{const{label:o,expectedStatuses:t=[],...s}=r,n=asDict(e),l=asDict(n?.config),c=asDict(n?.response),i=asDict(c?.data),d="number"==typeof c?.status?c.status:null,a="string"==typeof l?.method?l.method.toUpperCase():null,g="string"==typeof l?.url?l.url.split("?")[0]??null:null,u=o??([a,g].filter(Boolean).join(" ")||"Request");if("CanceledError"===n?.name||"ERR_CANCELED"===n?.code||!0===n?.__CANCEL__)return void logInfo(`${u} canceled`);if("RequestOfflineError"===n?.name)return void logInfo(`${u} not sent (offline)`);if((0,_extractApiError.isNoResponse)(e))return void logInfo(`${u} got no response`);if("WorkspaceChangedError"===n?.name||"workspace_changed"===i?.code)return void logInfo(`${u} refused (another workspace)`);if(null!==d&&t.includes(d))return void logInfo(`${u} refused (${d})`);const p="string"==typeof n?.message?n.message:e instanceof Error?e.message:null,f=(0,_redact.redactString)(null===d?`${u} failed`:`${u} failed (${d})`);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${f}${Colors.RESET}`,(0,_redact.redactString)(p??"")),safe(()=>remote?.log?.("error",f,[]));const E=(0,_index.getConfigValue)("correlationIdHeader",null),L=(0,_redact.redact)({source:"Logger.requestFailed",label:u,status:d,method:a,path:g,code:"string"==typeof i?.code?i.code:null,traceId:"string"==typeof i?.traceId?i.traceId:null,correlationId:E?headerValue(l?.headers,E):null,detail:p,...s});forwardErrorToRemote(new Error(f),L)},setUser=(e,r)=>{safe(()=>remote?.setUser?.(e,r))},setAttribute=(e,r)=>{safe(()=>remote?.setAttribute?.(e,r))},trackScreen=(e,r)=>{e!==currentScreen&&(currentScreen=e,screenHistory.push(e),screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit)),breadcrumb(`Screen: ${e}`,r))},getCurrentScreen=()=>currentScreen,getScreenHistory=()=>[...screenHistory],getBreadcrumbs=()=>[...breadcrumbs],Logger=exports.Logger={debug:logDebug,info:logInfo,warn:logWarning,error:logError,breadcrumb:breadcrumb,recordError:recordError,requestFailed:requestFailed,setUser:setUser,setAttribute:setAttribute,trackScreen:trackScreen,getCurrentScreen:getCurrentScreen,getScreenHistory:getScreenHistory,getBreadcrumbs:getBreadcrumbs};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.setRemoteLogger=exports.setDeviceContext=exports.getDeviceContext=exports.configureLogger=exports.Logger=void 0;var _index=require("../config/index.js"),_extractApiError=require("../errors/extractApiError.js"),_redact=require("./redact.js");const Colors={RESET:"",GRAY:"",BLUE:"",YELLOW:"",RED_BOLD:""},LogLevels={DEBUG:{level:"debug",color:Colors.GRAY},INFO:{level:"info",color:Colors.BLUE},WARN:{level:"warn",color:Colors.YELLOW},ERROR:{level:"error",color:Colors.RED_BOLD}},levels=["debug","info","warn","error"],isLogLevelAllowed=e=>{const r=(0,_index.getConfigValue)("logLevel","info");return levels.indexOf(e)>=levels.indexOf(r)},isEnabled=()=>(0,_index.getConfigValue)("loggingEnabled",!0);let remote=null;const setRemoteLogger=e=>{remote=e};exports.setRemoteLogger=setRemoteLogger;const safe=e=>{if(e)try{e()}catch{}};let deviceContext=null;const normalizeAttributeValue=e=>null==e?null:"string"==typeof e||"number"==typeof e||"boolean"==typeof e?e:String(e),setDeviceContext=e=>{if(deviceContext=e,e)for(const[r,o]of Object.entries(e))safe(()=>remote?.setAttribute?.(r,normalizeAttributeValue(o)))};exports.setDeviceContext=setDeviceContext;const getDeviceContext=()=>deviceContext;exports.getDeviceContext=getDeviceContext;const DEFAULT_LOGGER_OPTIONS={dedupeWindowMs:5e3,dedupeMaxPerWindow:1,screenHistoryLimit:20,breadcrumbLimit:50};let loggerOptions={...DEFAULT_LOGGER_OPTIONS};const configureLogger=e=>{const{redactKeys:r,...o}=e;void 0!==r&&(0,_redact.configureRedaction)(r),loggerOptions={...loggerOptions,...o},screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit)),trimBreadcrumbs()};exports.configureLogger=configureLogger;let currentScreen=null,screenHistory=[];const breadcrumbs=[],trimBreadcrumbs=()=>{const e=breadcrumbs.length-loggerOptions.breadcrumbLimit;e>0&&breadcrumbs.splice(0,e)},dedupeMap=new Map,MAX_DEDUPE_ENTRIES=200,dedupeKeyFor=e=>{const r=e.stack?.split("\n")[1]?.trim();return r?`${e.message}::${r}`:e.message},capDedupeMap=()=>{for(;dedupeMap.size>200;){const e=dedupeMap.keys().next().value;if(void 0===e)return;dedupeMap.delete(e)}},shouldForward=e=>{if(loggerOptions.dedupeWindowMs<=0)return{forward:!0};const r=Date.now(),o=dedupeMap.get(e);if(!o||r-o.windowStart>=loggerOptions.dedupeWindowMs){const t=o?.suppressedCount??0;return dedupeMap.set(e,{windowStart:r,count:1,suppressedCount:0}),capDedupeMap(),t>0?{forward:!0,suppressedCount:t}:{forward:!0}}return o.count+=1,o.count>loggerOptions.dedupeMaxPerWindow?(o.suppressedCount+=1,{forward:!1}):{forward:!0}},buildErrorContext=(e,r)=>{const o={...deviceContext};return null!==currentScreen&&(o.screen=currentScreen),r&&(o.suppressedCount=r),{...o,...e}},forwardErrorToRemote=(e,r)=>{const o=dedupeKeyFor(e),{forward:t,suppressedCount:s}=shouldForward(o);t&&safe(()=>remote?.recordError?.(e,buildErrorContext(r,s)))},logDebug=(e,...r)=>{isEnabled()&&isLogLevelAllowed(LogLevels.DEBUG.level)&&console.debug(`${LogLevels.DEBUG.color}[DEBUG]: ${(0,_redact.redactString)(e)}${Colors.RESET}`,...(0,_redact.redact)(r))},logInfo=(e,...r)=>{if(!isEnabled()||!isLogLevelAllowed(LogLevels.INFO.level))return;const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);console.info(`${LogLevels.INFO.color}[INFO]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("info",o,t))},logWarning=(e,...r)=>{if(!isEnabled()||!isLogLevelAllowed(LogLevels.WARN.level))return;const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);console.warn(`${LogLevels.WARN.color}[WARNING]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("warn",o,t))},logError=(e,...r)=>{const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("error",o,t));const s=r[0];void 0===s||(0,_extractApiError.isNoResponse)(s)||forwardErrorToRemote((0,_redact.redactError)(s),{source:"Logger.error",message:o})},breadcrumb=(e,r)=>{const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);breadcrumbs.push({message:o,data:t,timestampUtc:(new Date).toISOString()}),trimBreadcrumbs(),isEnabled()&&isLogLevelAllowed("info")&&console.info(`${Colors.BLUE}[BREADCRUMB]: ${o}${Colors.RESET}`,t??""),safe(()=>remote?.breadcrumb?.(o,t))},recordError=(e,r)=>{const o=(0,_redact.redactError)(e),t=(0,_redact.redact)(r);(0,_extractApiError.isNoResponse)(e)?logInfo(`No response: ${o.message}`):(isEnabled()&&isLogLevelAllowed("error")&&console.error(`${Colors.RED_BOLD}[RECORDED]: ${o.message}${Colors.RESET}`,t??""),forwardErrorToRemote(o,t))},asDict=e=>"object"==typeof e&&null!==e?e:null,headerValue=(e,r)=>{const o=asDict(e);if(!o)return null;const t="function"==typeof o.get?o.get.call(e,r):o[r]??o[r.toLowerCase()];return"string"==typeof t&&""!==t?t:null},requestFailed=(e,r={})=>{const{label:o,expectedStatuses:t=[],...s}=r,n=asDict(e),l=asDict(n?.config),c=asDict(n?.response),i=asDict(c?.data),d="number"==typeof c?.status?c.status:null,a="string"==typeof l?.method?l.method.toUpperCase():null,g="string"==typeof l?.url?l.url.split("?")[0]??null:null,u=o??([a,g].filter(Boolean).join(" ")||"Request");if("CanceledError"===n?.name||"ERR_CANCELED"===n?.code||!0===n?.__CANCEL__)return void logInfo(`${u} canceled`);if("RequestOfflineError"===n?.name)return void logInfo(`${u} not sent (offline)`);if((0,_extractApiError.isNoResponse)(e))return void logInfo(`${u} got no response`);if("WorkspaceChangedError"===n?.name||"workspace_changed"===i?.code)return void logInfo(`${u} refused (another workspace)`);if(null!==d&&t.includes(d))return void logInfo(`${u} refused (${d})`);const p="string"==typeof n?.message?n.message:e instanceof Error?e.message:null,f=(0,_redact.redactString)(null===d?`${u} failed`:`${u} failed (${d})`);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${f}${Colors.RESET}`,(0,_redact.redactString)(p??"")),safe(()=>remote?.log?.("error",f,[]));const E=(0,_index.getConfigValue)("correlationIdHeader",null),L=(0,_redact.redact)({source:"Logger.requestFailed",label:u,status:d,method:a,path:g,code:"string"==typeof i?.code?i.code:null,traceId:"string"==typeof i?.traceId?i.traceId:null,correlationId:E?headerValue(l?.headers,E):null,detail:p,...s});forwardErrorToRemote(new Error(f),L)},setUser=(e,r)=>{safe(()=>remote?.setUser?.(e,r))},setAttribute=(e,r)=>{safe(()=>remote?.setAttribute?.(e,r))},trackScreen=(e,r)=>{e!==currentScreen&&(currentScreen=e,screenHistory.push(e),screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit)),breadcrumb(`Screen: ${e}`,r))},getCurrentScreen=()=>currentScreen,getScreenHistory=()=>[...screenHistory],getBreadcrumbs=()=>[...breadcrumbs],Logger=exports.Logger={debug:logDebug,info:logInfo,warn:logWarning,error:logError,breadcrumb:breadcrumb,recordError:recordError,requestFailed:requestFailed,setUser:setUser,setAttribute:setAttribute,trackScreen:trackScreen,getCurrentScreen:getCurrentScreen,getScreenHistory:getScreenHistory,getBreadcrumbs:getBreadcrumbs};
@@ -1 +1 @@
1
- "use strict";import axios from"axios";import{getConfigValue}from"../config/index.js";import{isWorkspaceChangedResponse}from"./workspace.js";export const IDEMPOTENCY_KEY_HEADER="Idempotency-Key";export const isRetryableStatus=e=>"number"==typeof e&&(429===e||e>=500&&e<=599);const IDEMPOTENT_METHODS=new Set(["get","head","options","put","delete"]),NEVER_SENT_CODES=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","ENETUNREACH","EHOSTUNREACH"]);export const isNeverSentError=e=>!e.response&&"string"==typeof e.code&&NEVER_SENT_CODES.has(e.code);const MAX_RETRY_AFTER_MS=3e4;export const retryAfterMs=e=>{const t=e.response;if(!t)return null;const r=t.data,o=t.headers,s="function"==typeof o?.get?o.get("retry-after"):o?.["retry-after"];for(const e of[r?.retryAfterSeconds,s]){const t=Number(e);if(null!=e&&Number.isFinite(t)&&t>0)return 1e3*t}return null};const hasIdempotencyKey=e=>{const t=e?.headers,r="function"==typeof t?.get?t.get("Idempotency-Key"):t?.["Idempotency-Key"];return"string"==typeof r&&""!==r};export const isRetryableFailure=e=>{if(axios.isCancel(e)||"ERR_CANCELED"===e.code)return!1;if(isNeverSentError(e))return!0;const t=(e.config?.method??"get").toLowerCase(),r=IDEMPOTENT_METHODS.has(t),o=e.response?.status;if(void 0===o)return r;if(!isRetryableStatus(o))return!1;const s=retryAfterMs(e);return!(null!==s&&s>3e4)&&(r||(429===o||503===o)&&hasIdempotencyKey(e.config))};const DEFAULT_POLICY={retryDelayMs:e=>e<=1?0:2**e*1e3,shouldRetry:isRetryableFailure,onRetry:()=>{}},waitOrAbort=(e,t)=>new Promise(r=>{const onAbort=()=>{clearTimeout(o),r(!1)},o=setTimeout(()=>{t?.removeEventListener?.("abort",onAbort),r(!0)},e);t?.addEventListener?.("abort",onAbort,{once:!0})});export const attachRetry=(e,t={})=>{e.interceptors.response.use(void 0,async r=>{const o=r,s=o?.config;if(!s||!1===s.retry||isWorkspaceChangedResponse(o))return Promise.reject(r);const n="object"==typeof s.retry?s.retry:{},i={...DEFAULT_POLICY,retries:getConfigValue("retries"),...t,...n},c=(s.__retryAttempt??0)+1;if(c>i.retries||!i.shouldRetry(o))return Promise.reject(r);if(s.signal?.aborted)return Promise.reject(r);s.__retryAttempt=c,s.transformRequest=[e=>e],i.onRetry(c,o);const a=retryAfterMs(o)??i.retryDelayMs(c);return await waitOrAbort(a,s.signal)?e.request(s):Promise.reject(r)})};
1
+ "use strict";import axios from"axios";import{getConfigValue}from"../config/index.js";import{isWorkspaceChangedResponse}from"./workspace.js";export const IDEMPOTENCY_KEY_HEADER="Idempotency-Key";export const isRetryableStatus=e=>"number"==typeof e&&(429===e||e>=500&&e<=599);const IDEMPOTENT_METHODS=new Set(["get","head","options","put","delete"]),NEVER_SENT_CODES=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","ENETUNREACH","EHOSTUNREACH"]);export const isNeverSentError=e=>!e.response&&"string"==typeof e.code&&NEVER_SENT_CODES.has(e.code);const MAX_RETRY_AFTER_MS=3e4;export const retryAfterMs=e=>{const t=e.response;if(!t)return null;const r=t.data,o=t.headers,s="function"==typeof o?.get?o.get("retry-after"):o?.["retry-after"];for(const e of[r?.retryAfterSeconds,s]){const t=Number(e);if(null!=e&&Number.isFinite(t)&&t>0)return 1e3*t}return null};const hasIdempotencyKey=e=>{const t=e?.headers,r="function"==typeof t?.get?t.get("Idempotency-Key"):t?.["Idempotency-Key"];return"string"==typeof r&&""!==r};export const isRetryableFailure=e=>{if(axios.isCancel(e)||"ERR_CANCELED"===e.code)return!1;if(isNeverSentError(e))return!0;const t=(e.config?.method??"get").toLowerCase(),r=IDEMPOTENT_METHODS.has(t),o=e.response?.status;if(void 0===o)return r;if(!isRetryableStatus(o))return!1;const s=retryAfterMs(e);return!(null!==s&&s>3e4)&&(r||(429===o||503===o)&&hasIdempotencyKey(e.config))};const DEFAULT_POLICY={retryDelayMs:e=>Math.random()*Math.min(2e3,500*2**(e-1)),shouldRetry:isRetryableFailure,onRetry:()=>{}},waitOrAbort=(e,t)=>new Promise(r=>{const onAbort=()=>{clearTimeout(o),r(!1)},o=setTimeout(()=>{t?.removeEventListener?.("abort",onAbort),r(!0)},e);t?.addEventListener?.("abort",onAbort,{once:!0})});export const attachRetry=(e,t={})=>{e.interceptors.response.use(void 0,async r=>{const o=r,s=o?.config;if(!s||!1===s.retry||isWorkspaceChangedResponse(o))return Promise.reject(r);const n="object"==typeof s.retry?s.retry:{},i={...DEFAULT_POLICY,retries:getConfigValue("retries"),...t,...n},a=(s.__retryAttempt??0)+1;if(a>i.retries||!i.shouldRetry(o))return Promise.reject(r);if(s.signal?.aborted)return Promise.reject(r);s.__retryAttempt=a,1===a&&(s.__retryStartedAt=Date.now()),s.transformRequest=[e=>e];const c=retryAfterMs(o)??i.retryDelayMs(a),y=s.__retryStartedAt??Date.now();if(Date.now()-y+c>2e4)return Promise.reject(r);i.onRetry(a,o);return await waitOrAbort(c,s.signal)?e.request(s):Promise.reject(r)})};
@@ -1 +1 @@
1
- "use strict";import{getConfigValue}from"../config/index.js";import{isNoResponse}from"../errors/extractApiError.js";import{configureRedaction,redact,redactError,redactString}from"./redact.js";const Colors={RESET:"",GRAY:"",BLUE:"",YELLOW:"",RED_BOLD:""},LogLevels={DEBUG:{level:"debug",color:Colors.GRAY},INFO:{level:"info",color:Colors.BLUE},WARN:{level:"warn",color:Colors.YELLOW},ERROR:{level:"error",color:Colors.RED_BOLD}},isLogLevelAllowed=e=>{const r=["debug","info","warn","error"],o=getConfigValue("logLevel","info");return r.indexOf(e)>=r.indexOf(o)},isEnabled=()=>getConfigValue("loggingEnabled",!0);let remote=null;export const setRemoteLogger=e=>{remote=e};const safe=e=>{if(e)try{e()}catch{}};let deviceContext=null;const normalizeAttributeValue=e=>null==e?null:"string"==typeof e||"number"==typeof e||"boolean"==typeof e?e:String(e);export const setDeviceContext=e=>{if(deviceContext=e,e)for(const[r,o]of Object.entries(e))safe(()=>remote?.setAttribute?.(r,normalizeAttributeValue(o)))};export const getDeviceContext=()=>deviceContext;const DEFAULT_LOGGER_OPTIONS={dedupeWindowMs:5e3,dedupeMaxPerWindow:1,screenHistoryLimit:20,breadcrumbLimit:50};let loggerOptions={...DEFAULT_LOGGER_OPTIONS};export const configureLogger=e=>{const{redactKeys:r,...o}=e;void 0!==r&&configureRedaction(r),loggerOptions={...loggerOptions,...o},screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit)),trimBreadcrumbs()};let currentScreen=null,screenHistory=[];const breadcrumbs=[],trimBreadcrumbs=()=>{const e=breadcrumbs.length-loggerOptions.breadcrumbLimit;e>0&&breadcrumbs.splice(0,e)},dedupeMap=new Map,MAX_DEDUPE_ENTRIES=200,dedupeKeyFor=e=>{const r=e.stack?.split("\n")[1]?.trim();return r?`${e.message}::${r}`:e.message},capDedupeMap=()=>{for(;dedupeMap.size>200;){const e=dedupeMap.keys().next().value;if(void 0===e)return;dedupeMap.delete(e)}},shouldForward=e=>{if(loggerOptions.dedupeWindowMs<=0)return{forward:!0};const r=Date.now(),o=dedupeMap.get(e);if(!o||r-o.windowStart>=loggerOptions.dedupeWindowMs){const t=o?.suppressedCount??0;return dedupeMap.set(e,{windowStart:r,count:1,suppressedCount:0}),capDedupeMap(),t>0?{forward:!0,suppressedCount:t}:{forward:!0}}return o.count+=1,o.count>loggerOptions.dedupeMaxPerWindow?(o.suppressedCount+=1,{forward:!1}):{forward:!0}},buildErrorContext=(e,r)=>{const o={...deviceContext};return null!==currentScreen&&(o.screen=currentScreen),r&&(o.suppressedCount=r),{...o,...e}},forwardErrorToRemote=(e,r)=>{const o=dedupeKeyFor(e),{forward:t,suppressedCount:s}=shouldForward(o);t&&safe(()=>remote?.recordError?.(e,buildErrorContext(r,s)))},logDebug=(e,...r)=>{isEnabled()&&isLogLevelAllowed(LogLevels.DEBUG.level)&&console.debug(`${LogLevels.DEBUG.color}[DEBUG]: ${redactString(e)}${Colors.RESET}`,...redact(r))},logInfo=(e,...r)=>{const o=redactString(e),t=redact(r);isEnabled()&&isLogLevelAllowed(LogLevels.INFO.level)&&(console.info(`${LogLevels.INFO.color}[INFO]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("info",o,t)))},logWarning=(e,...r)=>{const o=redactString(e),t=redact(r);isEnabled()&&isLogLevelAllowed(LogLevels.WARN.level)&&(console.warn(`${LogLevels.WARN.color}[WARNING]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("warn",o,t)))},logError=(e,...r)=>{const o=redactString(e),t=redact(r);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("error",o,t));const s=r[0];void 0===s||isNoResponse(s)||forwardErrorToRemote(redactError(s),{source:"Logger.error",message:o})},breadcrumb=(e,r)=>{const o=redactString(e),t=redact(r);breadcrumbs.push({message:o,data:t,timestampUtc:(new Date).toISOString()}),trimBreadcrumbs(),isEnabled()&&isLogLevelAllowed("info")&&console.info(`${Colors.BLUE}[BREADCRUMB]: ${o}${Colors.RESET}`,t??""),safe(()=>remote?.breadcrumb?.(o,t))},recordError=(e,r)=>{const o=redactError(e),t=redact(r);isNoResponse(e)?logInfo(`No response: ${o.message}`):(isEnabled()&&isLogLevelAllowed("error")&&console.error(`${Colors.RED_BOLD}[RECORDED]: ${o.message}${Colors.RESET}`,t??""),forwardErrorToRemote(o,t))},asDict=e=>"object"==typeof e&&null!==e?e:null,headerValue=(e,r)=>{const o=asDict(e);if(!o)return null;const t="function"==typeof o.get?o.get.call(e,r):o[r]??o[r.toLowerCase()];return"string"==typeof t&&""!==t?t:null},requestFailed=(e,r={})=>{const{label:o,expectedStatuses:t=[],...s}=r,n=asDict(e),l=asDict(n?.config),c=asDict(n?.response),i=asDict(c?.data),a="number"==typeof c?.status?c.status:null,d="string"==typeof l?.method?l.method.toUpperCase():null,u="string"==typeof l?.url?l.url.split("?")[0]??null:null,g=o??([d,u].filter(Boolean).join(" ")||"Request");if("CanceledError"===n?.name||"ERR_CANCELED"===n?.code||!0===n?.__CANCEL__)return void logInfo(`${g} canceled`);if("RequestOfflineError"===n?.name)return void logInfo(`${g} not sent (offline)`);if(isNoResponse(e))return void logInfo(`${g} got no response`);if("WorkspaceChangedError"===n?.name||"workspace_changed"===i?.code)return void logInfo(`${g} refused (another workspace)`);if(null!==a&&t.includes(a))return void logInfo(`${g} refused (${a})`);const p="string"==typeof n?.message?n.message:e instanceof Error?e.message:null,f=redactString(null===a?`${g} failed`:`${g} failed (${a})`);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${f}${Colors.RESET}`,redactString(p??"")),safe(()=>remote?.log?.("error",f,[]));const E=getConfigValue("correlationIdHeader",null),m=redact({source:"Logger.requestFailed",label:g,status:a,method:d,path:u,code:"string"==typeof i?.code?i.code:null,traceId:"string"==typeof i?.traceId?i.traceId:null,correlationId:E?headerValue(l?.headers,E):null,detail:p,...s});forwardErrorToRemote(new Error(f),m)},setUser=(e,r)=>{safe(()=>remote?.setUser?.(e,r))},setAttribute=(e,r)=>{safe(()=>remote?.setAttribute?.(e,r))},trackScreen=(e,r)=>{e!==currentScreen&&(currentScreen=e,screenHistory.push(e),screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit)),breadcrumb(`Screen: ${e}`,r))},getCurrentScreen=()=>currentScreen,getScreenHistory=()=>[...screenHistory],getBreadcrumbs=()=>[...breadcrumbs];export const Logger={debug:logDebug,info:logInfo,warn:logWarning,error:logError,breadcrumb:breadcrumb,recordError:recordError,requestFailed:requestFailed,setUser:setUser,setAttribute:setAttribute,trackScreen:trackScreen,getCurrentScreen:getCurrentScreen,getScreenHistory:getScreenHistory,getBreadcrumbs:getBreadcrumbs};
1
+ "use strict";import{getConfigValue}from"../config/index.js";import{isNoResponse}from"../errors/extractApiError.js";import{configureRedaction,redact,redactError,redactString}from"./redact.js";const Colors={RESET:"",GRAY:"",BLUE:"",YELLOW:"",RED_BOLD:""},LogLevels={DEBUG:{level:"debug",color:Colors.GRAY},INFO:{level:"info",color:Colors.BLUE},WARN:{level:"warn",color:Colors.YELLOW},ERROR:{level:"error",color:Colors.RED_BOLD}},levels=["debug","info","warn","error"],isLogLevelAllowed=e=>{const r=getConfigValue("logLevel","info");return levels.indexOf(e)>=levels.indexOf(r)},isEnabled=()=>getConfigValue("loggingEnabled",!0);let remote=null;export const setRemoteLogger=e=>{remote=e};const safe=e=>{if(e)try{e()}catch{}};let deviceContext=null;const normalizeAttributeValue=e=>null==e?null:"string"==typeof e||"number"==typeof e||"boolean"==typeof e?e:String(e);export const setDeviceContext=e=>{if(deviceContext=e,e)for(const[r,o]of Object.entries(e))safe(()=>remote?.setAttribute?.(r,normalizeAttributeValue(o)))};export const getDeviceContext=()=>deviceContext;const DEFAULT_LOGGER_OPTIONS={dedupeWindowMs:5e3,dedupeMaxPerWindow:1,screenHistoryLimit:20,breadcrumbLimit:50};let loggerOptions={...DEFAULT_LOGGER_OPTIONS};export const configureLogger=e=>{const{redactKeys:r,...o}=e;void 0!==r&&configureRedaction(r),loggerOptions={...loggerOptions,...o},screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit)),trimBreadcrumbs()};let currentScreen=null,screenHistory=[];const breadcrumbs=[],trimBreadcrumbs=()=>{const e=breadcrumbs.length-loggerOptions.breadcrumbLimit;e>0&&breadcrumbs.splice(0,e)},dedupeMap=new Map,MAX_DEDUPE_ENTRIES=200,dedupeKeyFor=e=>{const r=e.stack?.split("\n")[1]?.trim();return r?`${e.message}::${r}`:e.message},capDedupeMap=()=>{for(;dedupeMap.size>200;){const e=dedupeMap.keys().next().value;if(void 0===e)return;dedupeMap.delete(e)}},shouldForward=e=>{if(loggerOptions.dedupeWindowMs<=0)return{forward:!0};const r=Date.now(),o=dedupeMap.get(e);if(!o||r-o.windowStart>=loggerOptions.dedupeWindowMs){const t=o?.suppressedCount??0;return dedupeMap.set(e,{windowStart:r,count:1,suppressedCount:0}),capDedupeMap(),t>0?{forward:!0,suppressedCount:t}:{forward:!0}}return o.count+=1,o.count>loggerOptions.dedupeMaxPerWindow?(o.suppressedCount+=1,{forward:!1}):{forward:!0}},buildErrorContext=(e,r)=>{const o={...deviceContext};return null!==currentScreen&&(o.screen=currentScreen),r&&(o.suppressedCount=r),{...o,...e}},forwardErrorToRemote=(e,r)=>{const o=dedupeKeyFor(e),{forward:t,suppressedCount:s}=shouldForward(o);t&&safe(()=>remote?.recordError?.(e,buildErrorContext(r,s)))},logDebug=(e,...r)=>{isEnabled()&&isLogLevelAllowed(LogLevels.DEBUG.level)&&console.debug(`${LogLevels.DEBUG.color}[DEBUG]: ${redactString(e)}${Colors.RESET}`,...redact(r))},logInfo=(e,...r)=>{if(!isEnabled()||!isLogLevelAllowed(LogLevels.INFO.level))return;const o=redactString(e),t=redact(r);console.info(`${LogLevels.INFO.color}[INFO]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("info",o,t))},logWarning=(e,...r)=>{if(!isEnabled()||!isLogLevelAllowed(LogLevels.WARN.level))return;const o=redactString(e),t=redact(r);console.warn(`${LogLevels.WARN.color}[WARNING]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("warn",o,t))},logError=(e,...r)=>{const o=redactString(e),t=redact(r);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("error",o,t));const s=r[0];void 0===s||isNoResponse(s)||forwardErrorToRemote(redactError(s),{source:"Logger.error",message:o})},breadcrumb=(e,r)=>{const o=redactString(e),t=redact(r);breadcrumbs.push({message:o,data:t,timestampUtc:(new Date).toISOString()}),trimBreadcrumbs(),isEnabled()&&isLogLevelAllowed("info")&&console.info(`${Colors.BLUE}[BREADCRUMB]: ${o}${Colors.RESET}`,t??""),safe(()=>remote?.breadcrumb?.(o,t))},recordError=(e,r)=>{const o=redactError(e),t=redact(r);isNoResponse(e)?logInfo(`No response: ${o.message}`):(isEnabled()&&isLogLevelAllowed("error")&&console.error(`${Colors.RED_BOLD}[RECORDED]: ${o.message}${Colors.RESET}`,t??""),forwardErrorToRemote(o,t))},asDict=e=>"object"==typeof e&&null!==e?e:null,headerValue=(e,r)=>{const o=asDict(e);if(!o)return null;const t="function"==typeof o.get?o.get.call(e,r):o[r]??o[r.toLowerCase()];return"string"==typeof t&&""!==t?t:null},requestFailed=(e,r={})=>{const{label:o,expectedStatuses:t=[],...s}=r,n=asDict(e),l=asDict(n?.config),c=asDict(n?.response),i=asDict(c?.data),a="number"==typeof c?.status?c.status:null,d="string"==typeof l?.method?l.method.toUpperCase():null,u="string"==typeof l?.url?l.url.split("?")[0]??null:null,g=o??([d,u].filter(Boolean).join(" ")||"Request");if("CanceledError"===n?.name||"ERR_CANCELED"===n?.code||!0===n?.__CANCEL__)return void logInfo(`${g} canceled`);if("RequestOfflineError"===n?.name)return void logInfo(`${g} not sent (offline)`);if(isNoResponse(e))return void logInfo(`${g} got no response`);if("WorkspaceChangedError"===n?.name||"workspace_changed"===i?.code)return void logInfo(`${g} refused (another workspace)`);if(null!==a&&t.includes(a))return void logInfo(`${g} refused (${a})`);const p="string"==typeof n?.message?n.message:e instanceof Error?e.message:null,f=redactString(null===a?`${g} failed`:`${g} failed (${a})`);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${f}${Colors.RESET}`,redactString(p??"")),safe(()=>remote?.log?.("error",f,[]));const E=getConfigValue("correlationIdHeader",null),m=redact({source:"Logger.requestFailed",label:g,status:a,method:d,path:u,code:"string"==typeof i?.code?i.code:null,traceId:"string"==typeof i?.traceId?i.traceId:null,correlationId:E?headerValue(l?.headers,E):null,detail:p,...s});forwardErrorToRemote(new Error(f),m)},setUser=(e,r)=>{safe(()=>remote?.setUser?.(e,r))},setAttribute=(e,r)=>{safe(()=>remote?.setAttribute?.(e,r))},trackScreen=(e,r)=>{e!==currentScreen&&(currentScreen=e,screenHistory.push(e),screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit)),breadcrumb(`Screen: ${e}`,r))},getCurrentScreen=()=>currentScreen,getScreenHistory=()=>[...screenHistory],getBreadcrumbs=()=>[...breadcrumbs];export const Logger={debug:logDebug,info:logInfo,warn:logWarning,error:logError,breadcrumb:breadcrumb,recordError:recordError,requestFailed:requestFailed,setUser:setUser,setAttribute:setAttribute,trackScreen:trackScreen,getCurrentScreen:getCurrentScreen,getScreenHistory:getScreenHistory,getBreadcrumbs:getBreadcrumbs};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/mobile-core",
3
- "version": "0.16.4",
3
+ "version": "0.16.5",
4
4
  "description": "Platform layer for Webority React Native apps: HTTP clients, auth/token storage, config, logging, formatters, validators, network status, permissions, storage, version checks and over-the-air updates. No UI.",
5
5
  "keywords": [
6
6
  "react-native",