@webority/mobile-core 0.10.0 → 0.11.0
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.
- package/README.md +3 -2
- package/lib/commonjs/api/userClient.js +1 -1
- package/lib/commonjs/formatters/currency.js +1 -1
- package/lib/commonjs/formatters/formatConfig.js +1 -1
- package/lib/commonjs/formatters/house.js +1 -1
- package/lib/commonjs/formatters/number.js +1 -1
- package/lib/commonjs/logger/index.js +1 -1
- package/lib/commonjs/permissions/index.js +1 -1
- package/lib/commonjs/push/push.js +1 -1
- package/lib/commonjs/push/status.js +1 -1
- package/lib/module/api/userClient.js +1 -1
- package/lib/module/formatters/currency.js +1 -1
- package/lib/module/formatters/formatConfig.js +1 -1
- package/lib/module/formatters/house.js +1 -1
- package/lib/module/formatters/number.js +1 -1
- package/lib/module/logger/index.js +1 -1
- package/lib/module/permissions/index.js +1 -1
- package/lib/module/push/push.js +1 -1
- package/lib/module/push/status.js +1 -1
- package/lib/typescript/commonjs/formatters/currency.d.ts +2 -0
- package/lib/typescript/commonjs/formatters/formatConfig.d.ts +40 -4
- package/lib/typescript/commonjs/formatters/house.d.ts +7 -2
- package/lib/typescript/commonjs/formatters/index.d.ts +1 -1
- package/lib/typescript/commonjs/formatters/number.d.ts +2 -1
- package/lib/typescript/commonjs/index.d.ts +1 -1
- package/lib/typescript/commonjs/permissions/index.d.ts +7 -2
- package/lib/typescript/commonjs/push/push.d.ts +3 -1
- package/lib/typescript/commonjs/push/status.d.ts +8 -1
- package/lib/typescript/module/formatters/currency.d.ts +2 -0
- package/lib/typescript/module/formatters/formatConfig.d.ts +40 -4
- package/lib/typescript/module/formatters/house.d.ts +7 -2
- package/lib/typescript/module/formatters/index.d.ts +1 -1
- package/lib/typescript/module/formatters/number.d.ts +2 -1
- package/lib/typescript/module/index.d.ts +1 -1
- package/lib/typescript/module/permissions/index.d.ts +7 -2
- package/lib/typescript/module/push/push.d.ts +3 -1
- package/lib/typescript/module/push/status.d.ts +8 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,8 +83,9 @@ settings switch its `status` and `enabled`. The library does not remember the sw
|
|
|
83
83
|
keeps push on calls `enablePush` at each start. `setBadgeCount(count)` sets the app icon badge.
|
|
84
84
|
|
|
85
85
|
- `enablePush({ prompt: false })` never shows the permission prompt: a phone already granted
|
|
86
|
-
registers silently, and any other resolves with its status (`
|
|
87
|
-
been asked yet, `denied` when refused
|
|
86
|
+
registers silently, and any other resolves with its status (`undetermined` when the person has not
|
|
87
|
+
been asked yet, `denied` when refused and the prompt can still show, `blocked` when only
|
|
88
|
+
Settings can turn it on). Call it at sign-in, and call `enablePush()` when the
|
|
88
89
|
person reaches a moment where asking makes sense.
|
|
89
90
|
- Every registered device carries `apnsEnvironment`: `Development` or `Production` on iOS, read
|
|
90
91
|
from the build's `aps-environment` (expo-application), so the server sends each phone to the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.SESSION_TERMINATION_CODES=exports.SESSION_INVALID_HEADER=exports.RequestOfflineError=void 0,Object.defineProperty(exports,"SIGN_OUT_REASON_HEADER",{enumerable:!0,get:function(){return _tokenRefresh.SIGN_OUT_REASON_HEADER}}),exports.default=void 0,Object.defineProperty(exports,"injectStore",{enumerable:!0,get:function(){return _tokenRefresh.injectStore}}),Object.defineProperty(exports,"injectUserAuth",{enumerable:!0,get:function(){return _tokenRefresh.injectUserAuth}}),Object.defineProperty(exports,"resetRefreshState",{enumerable:!0,get:function(){return _tokenRefresh.resetRefreshState}});var _axios=_interopRequireWildcard(require("axios")),_authStore=require("../auth/authStore.js"),_index=require("../config/index.js"),_index2=require("../logger/index.js"),_networkStatus=require("../network/networkStatus.js");require("../types/axios.js");var _baseUrl=require("./baseUrl.js"),_clientHeaders=require("./clientHeaders.js"),_curl=require("./curl.js"),_minAppVersion=require("./minAppVersion.js"),_multipart=require("./multipart.js"),_requestDefaults=require("./requestDefaults.js"),_responseBodyText=require("./responseBodyText.js"),_retry=require("./retry.js"),_tokenRefresh=require("./tokenRefresh.js"),_workspace=require("./workspace.js");function _interopRequireWildcard(e,r){if("function"==typeof WeakMap)var t=new WeakMap,s=new WeakMap;return(_interopRequireWildcard=function(e,r){if(!r&&e&&e.__esModule)return e;var o,n,i={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return i;if(o=r?s:t){if(o.has(e))return o.get(e);o.set(e,i)}for(const r in e)"default"!==r&&{}.hasOwnProperty.call(e,r)&&((n=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,r))&&(n.get||n.set)?o(i,r,n):i[r]=e[r]);return i})(e,r)}class RequestOfflineError extends Error{constructor(e="Request blocked: device is offline"){super(e),this.name="RequestOfflineError",Object.setPrototypeOf(this,RequestOfflineError.prototype)}}exports.RequestOfflineError=RequestOfflineError;class NoAccessTokenError extends Error{constructor(){super("No access token available"),this.name="NoAccessTokenError",Object.setPrototypeOf(this,NoAccessTokenError.prototype)}}const SESSION_TERMINATION_CODES=exports.SESSION_TERMINATION_CODES={TERMINATED:"SESSION_TERMINATED",EXPIRED:"SESSION_EXPIRED"},TERMINATION_CODES=new Set(Object.values(SESSION_TERMINATION_CODES)),SESSION_INVALID_HEADER=exports.SESSION_INVALID_HEADER="x-security-stamp-invalid",hasSessionInvalidHeader=e=>{if(!e||"object"!=typeof e)return!1;const r=e.get,t="function"==typeof r?r.call(e,SESSION_INVALID_HEADER):e[SESSION_INVALID_HEADER];return"true"===String(t).toLowerCase()},getSessionTerminationCode=e=>{if(!e||"object"!=typeof e)return;const r=e,t=r.error,s=[r.code,r.errorCode,t&&"object"==typeof t?t.code:void 0];for(const e of s)if("string"==typeof e&&TERMINATION_CODES.has(e))return e},endReplacement=e=>{e?._endReplacement?.(),e&&(e._endReplacement=void 0)},readSentToken=e=>{const r=e.headers instanceof _axios.AxiosHeaders?e.headers.get("Authorization"):void 0;return"string"==typeof r&&r.startsWith("Bearer ")?r.slice(7):null},userClient=_axios.default.create({headers:{"Content-Type":"application/json"}});(0,_minAppVersion.readMinAppVersion)(userClient),(0,_retry.attachRetry)(userClient);const setAuthHeader=(e,r)=>{e.headers instanceof _axios.AxiosHeaders?e.headers.set("Authorization",`Bearer ${r}`):e.headers=_axios.AxiosHeaders.from({...e.headers,Authorization:`Bearer ${r}`})},isRefreshTokenRequest=e=>{const r=(0,_tokenRefresh.getRefreshPath)();return!!r&&!!e?.includes(r)};userClient.interceptors.request.use(e=>(e.replacesSession&&!isRefreshTokenRequest(e.url)
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.SESSION_TERMINATION_CODES=exports.SESSION_INVALID_HEADER=exports.RequestOfflineError=void 0,Object.defineProperty(exports,"SIGN_OUT_REASON_HEADER",{enumerable:!0,get:function(){return _tokenRefresh.SIGN_OUT_REASON_HEADER}}),exports.default=void 0,Object.defineProperty(exports,"injectStore",{enumerable:!0,get:function(){return _tokenRefresh.injectStore}}),Object.defineProperty(exports,"injectUserAuth",{enumerable:!0,get:function(){return _tokenRefresh.injectUserAuth}}),Object.defineProperty(exports,"resetRefreshState",{enumerable:!0,get:function(){return _tokenRefresh.resetRefreshState}});var _axios=_interopRequireWildcard(require("axios")),_authStore=require("../auth/authStore.js"),_index=require("../config/index.js"),_index2=require("../logger/index.js"),_networkStatus=require("../network/networkStatus.js");require("../types/axios.js");var _baseUrl=require("./baseUrl.js"),_clientHeaders=require("./clientHeaders.js"),_curl=require("./curl.js"),_minAppVersion=require("./minAppVersion.js"),_multipart=require("./multipart.js"),_requestDefaults=require("./requestDefaults.js"),_responseBodyText=require("./responseBodyText.js"),_retry=require("./retry.js"),_tokenRefresh=require("./tokenRefresh.js"),_workspace=require("./workspace.js");function _interopRequireWildcard(e,r){if("function"==typeof WeakMap)var t=new WeakMap,s=new WeakMap;return(_interopRequireWildcard=function(e,r){if(!r&&e&&e.__esModule)return e;var o,n,i={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return i;if(o=r?s:t){if(o.has(e))return o.get(e);o.set(e,i)}for(const r in e)"default"!==r&&{}.hasOwnProperty.call(e,r)&&((n=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,r))&&(n.get||n.set)?o(i,r,n):i[r]=e[r]);return i})(e,r)}class RequestOfflineError extends Error{constructor(e="Request blocked: device is offline"){super(e),this.name="RequestOfflineError",Object.setPrototypeOf(this,RequestOfflineError.prototype)}}exports.RequestOfflineError=RequestOfflineError;class NoAccessTokenError extends Error{constructor(){super("No access token available"),this.name="NoAccessTokenError",Object.setPrototypeOf(this,NoAccessTokenError.prototype)}}const SESSION_TERMINATION_CODES=exports.SESSION_TERMINATION_CODES={TERMINATED:"SESSION_TERMINATED",EXPIRED:"SESSION_EXPIRED"},TERMINATION_CODES=new Set(Object.values(SESSION_TERMINATION_CODES)),SESSION_INVALID_HEADER=exports.SESSION_INVALID_HEADER="x-security-stamp-invalid",hasSessionInvalidHeader=e=>{if(!e||"object"!=typeof e)return!1;const r=e.get,t="function"==typeof r?r.call(e,SESSION_INVALID_HEADER):e[SESSION_INVALID_HEADER];return"true"===String(t).toLowerCase()},getSessionTerminationCode=e=>{if(!e||"object"!=typeof e)return;const r=e,t=r.error,s=[r.code,r.errorCode,t&&"object"==typeof t?t.code:void 0];for(const e of s)if("string"==typeof e&&TERMINATION_CODES.has(e))return e},endReplacement=e=>{e?._endReplacement?.(),e&&(e._endReplacement=void 0)},closeWindowIfTransformThrows=e=>{if(e._transformGuarded)return;e._transformGuarded=!0;const r=[].concat(e.transformRequest??[]);e.transformRequest=[function guarded(e,t){try{return r.reduce((e,r)=>r.call(this,e,t),e)}catch(e){throw endReplacement(this),e}}]},readSentToken=e=>{const r=e.headers instanceof _axios.AxiosHeaders?e.headers.get("Authorization"):void 0;return"string"==typeof r&&r.startsWith("Bearer ")?r.slice(7):null},userClient=_axios.default.create({headers:{"Content-Type":"application/json"}});(0,_minAppVersion.readMinAppVersion)(userClient),(0,_retry.attachRetry)(userClient);const setAuthHeader=(e,r)=>{e.headers instanceof _axios.AxiosHeaders?e.headers.set("Authorization",`Bearer ${r}`):e.headers=_axios.AxiosHeaders.from({...e.headers,Authorization:`Bearer ${r}`})},isRefreshTokenRequest=e=>{const r=(0,_tokenRefresh.getRefreshPath)();return!!r&&!!e?.includes(r)};userClient.interceptors.request.use(e=>{if(e.replacesSession&&!isRefreshTokenRequest(e.url)){const r=e;r._endReplacement=(0,_tokenRefresh.beginSessionReplacement)(),closeWindowIfTransformThrows(r)}return e}),(0,_baseUrl.applyConfiguredBaseUrl)(userClient),(0,_requestDefaults.applyRequestDefaults)(userClient),(0,_multipart.sendFormDataAsMultipart)(userClient),userClient.interceptors.request.use(e=>((0,_index.getConfigValue)("logCurl")&&(0,_curl.logCurl)(e),e)),(0,_clientHeaders.applyClientHeaders)(userClient),userClient.interceptors.request.use(async e=>{endReplacement(e);if(!1===(await(0,_networkStatus.getLastKnownNetworkStatus)()).isConnected)return _index2.Logger.warn(`Request blocked: device is offline. URL: ${e.url}`),Promise.reject(new RequestOfflineError);try{if(isRefreshTokenRequest(e.url))return e;await(0,_clientHeaders.stampAccountId)(e,(0,_tokenRefresh.getAccountIdProvider)());const r=await(0,_authStore.getToken)(_authStore.ACCESS_TOKEN_KEY);if(!r?.token)throw new NoAccessTokenError;const t=Date.now(),s=Date.parse(r.expiry);if(s<=t+3e4){_index2.Logger.info("Access token expired or about to expire, refreshing before request");const r=await(0,_tokenRefresh.refreshAccessToken)();setAuthHeader(e,r)}else setAuthHeader(e,r.token);return e}catch(r){return r instanceof NoAccessTokenError?_index2.Logger.info(`Request not sent: signed out. URL: ${e.url}`):_index2.Logger.error("Failed to attach token:",(0,_tokenRefresh.getErrorMessage)(r)),Promise.reject(r)}},e=>(_index2.Logger.error("Request error:",(0,_tokenRefresh.getErrorMessage)(e)),Promise.reject(e))),userClient.interceptors.response.use(async e=>{const r=e.config;if(r._endReplacement)try{await(0,_tokenRefresh.storeReplacementSession)(e.data)}finally{endReplacement(r)}return e},async e=>{if(endReplacement(e?.config),_axios.default.isCancel(e))return Promise.reject(e);if(e instanceof RequestOfflineError||e instanceof NoAccessTokenError)return Promise.reject(e);if(!_axios.default.isAxiosError(e))return _index2.Logger.error(`Non-axios error in response interceptor: ${(0,_tokenRefresh.getErrorMessage)(e)}`),Promise.reject(e);const r=e,t=r.config;if(!r.response)return t?.skipErrorLog||_index2.Logger.info(`Network error or no response from server: ${r.message}, URL: ${t?.url}`),Promise.reject(e);if((0,_workspace.isWorkspaceChangedResponse)(r))return _index2.Logger.info(`Refused for another workspace. URL: ${t?.url}`),Promise.reject(new _workspace.WorkspaceChangedError("Refused for another workspace",{response:r.response,config:t,cause:e}));if(401===r.response.status&&t&&!t._replayedWithCurrentToken&&!t.replacesSession&&!isRefreshTokenRequest(t.url)&&(await(0,_tokenRefresh.waitForSessionReplacement)(),await(0,_tokenRefresh.currentTokenIfReplaced)(readSentToken(t)))){const r=await(0,_clientHeaders.readAccountId)((0,_tokenRefresh.getAccountIdProvider)());return(t._accountId??null)!==r?(_index2.Logger.info(`Workspace changed in flight; not sent again. URL: ${t.url}`),Promise.reject(new _workspace.WorkspaceChangedError("Workspace changed in flight",{config:t,cause:e}))):(_index2.Logger.info(`Session changed while the request was in flight; sending it again. URL: ${t.url}`),t._replayedWithCurrentToken=!0,userClient(t))}if(401===r.response.status&&t&&!t._retry){if(isRefreshTokenRequest(t.url))return Promise.reject(e);const s=(0,_tokenRefresh.readSignOutReason)(r.response.headers),o=getSessionTerminationCode(r.response.data)??(hasSessionInvalidHeader(r.response.headers)||null!==s?SESSION_TERMINATION_CODES.TERMINATED:void 0);if(o)return _index2.Logger.warn(`Session ${o}, logging out without refresh. URL: ${t.url}`),(0,_tokenRefresh.resetRefreshState)(),await(0,_tokenRefresh.endSessionAndLogout)("terminated",s),Promise.reject(e);if(_index2.Logger.warn(`Unauthorized URL: ${t.url}`),t._retry=!0,(0,_tokenRefresh.isRefreshInFlight)())return(0,_tokenRefresh.queueBehindRefresh)().then(e=>(_index2.Logger.info("Retrying request after token refresh:",t.url),setAuthHeader(t,e),userClient(t))).catch(e=>(_index2.Logger.error("Failed to retry request after token refresh:",(0,_tokenRefresh.getErrorMessage)(e)),Promise.reject(e)));try{const e=await(0,_tokenRefresh.refreshAccessToken)();return setAuthHeader(t,e),userClient(t)}catch(e){return Promise.reject(e)}}return t?.skipErrorLog||_index2.Logger.error(`Response error: ${(0,_responseBodyText.responseBodyText)(r.response?.data,r.message)}, URL: ${t?.url}, Status: ${r.response.status}`),Promise.reject(e)});var _default=exports.default=userClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatCurrency=void 0;var _formatConfig=require("./formatConfig.js"),_intlCache=require("./intlCache.js");const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,indianGroupingFallback=(r,t)=>{const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatCurrency=void 0;var _formatConfig=require("./formatConfig.js"),_intlCache=require("./intlCache.js");const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,indianGroupingFallback=(r,t)=>{const{decimal:e,group:n}=(0,_formatConfig.numberSeparators)()??{decimal:".",group:","},i=r<0?"-":"",o=Math.abs(r).toFixed(t),[m,a]=o.split("."),u=m.length>3?m.slice(-3):m,c=m.length>3?m.slice(0,-3):"";return i+(c?c.replace(/\B(?=(\d{2})+(?!\d))/g,n)+n+u:u)+(a?`${e}${a}`:"")},toAmount=r=>{if(null==r||"string"==typeof r&&""===r.trim())return null;const t="number"==typeof r?r:Number(r);return Number.isFinite(t)?t:null},currencyDigits=(r,t)=>(0,_intlCache.numberFormat)(r,{style:"currency",currency:t}).resolvedOptions().maximumFractionDigits??2,formatCurrency=(r,t={})=>{const{currency:e="INR",locale:n=(0,_formatConfig.configuredLocale)()??"en-IN",minimumFractionDigits:i,maximumFractionDigits:o,stripSymbol:m=!1,empty:a=((0,_formatConfig.isFormatterConfigured)("locale")||(0,_formatConfig.isFormatterConfigured)("empty")?(0,_formatConfig.getFormatterConfig)().empty:""),...u}=t,c=toAmount(r);if(null===c)return a;if(hasIntlNumber())try{const r=o??currencyDigits(n,e),t=i??(Number.isInteger(c)?0:r),a=(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(n,{...u,style:"currency",currency:e,minimumFractionDigits:t,maximumFractionDigits:Math.max(t,r)}),c);return m?a.replace(/[^\d,.\s\-+]/g,"").trim():a}catch{}const l=indianGroupingFallback(c,i??(Number.isInteger(c)?0:2));return m?l:"INR"===e?`₹${l}`:`${e} ${l}`};exports.formatCurrency=formatCurrency;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.isFormatterConfigured=exports.groupingForLocale=exports.getFormatterConfig=exports.configuredLocale=exports.configureFormatters=void 0;const DEFAULTS={zone:"IST",locale:"en-IN",empty:"-"};let current={...DEFAULTS},configured=new Set;const configureFormatters=e=>{if(void 0===e)return current={...DEFAULTS},void(configured=new Set);for(const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.styledNumber=exports.numberSeparators=exports.isFormatterConfigured=exports.groupingForLocale=exports.getFormatterConfig=exports.configuredLocale=exports.configureFormatters=void 0;const DEFAULTS={zone:"IST",locale:"en-IN",empty:"-"},SEPARATORS={PointWithCommaGroups:{decimal:".",group:","},CommaWithPointGroups:{decimal:",",group:"."},CommaWithSpaceGroups:{decimal:",",group:" "},PointWithSpaceGroups:{decimal:".",group:" "}},DATE_ORDERS=["DayMonthNameYear","DayMonthYear","MonthDayYear","YearMonthDay"];let current={...DEFAULTS},configured=new Set;const configureFormatters=e=>{if(void 0===e)return current={...DEFAULTS},void(configured=new Set);if(void 0!==e.numberStyle&&!Object.hasOwn(SEPARATORS,e.numberStyle))throw new RangeError(`Unknown number style "${e.numberStyle}"; expected one of ${Object.keys(SEPARATORS).join(", ")}.`);if(void 0!==e.dateOrder&&!DATE_ORDERS.includes(e.dateOrder))throw new RangeError(`Unknown date order "${e.dateOrder}"; expected one of ${DATE_ORDERS.join(", ")}.`);for(const r of Object.keys(e)){const o=e[r];void 0!==o&&(current={...current,[r]:o},configured.add(r))}};exports.configureFormatters=configureFormatters;const getFormatterConfig=()=>({...current});exports.getFormatterConfig=getFormatterConfig;const isFormatterConfigured=e=>configured.has(e);exports.isFormatterConfigured=isFormatterConfigured;const configuredLocale=()=>configured.has("locale")?current.locale:null;exports.configuredLocale=configuredLocale;const groupingForLocale=e=>/-IN(?:-|$)/i.test(e)?"indian":"international";exports.groupingForLocale=groupingForLocale;const numberSeparators=()=>void 0===current.numberStyle?null:SEPARATORS[current.numberStyle];exports.numberSeparators=numberSeparators;const styledNumber=(e,r)=>{const o=numberSeparators();return null===o?e.format(r):e.formatToParts(r).map(e=>"decimal"===e.type?o.decimal:"group"===e.type?o.group:e.value).join("")};exports.styledNumber=styledNumber;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatTime=exports.formatRelative=exports.formatPercent=exports.formatNumber=exports.formatMinor=exports.formatDateTime=exports.formatDate=void 0;var _formatConfig=require("./formatConfig.js"),_intlCache=require("./intlCache.js");const MONTHS=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],IST_OFFSET_MINUTES=330,IST_NAMES=["IST","Asia/Kolkata","Asia/Calcutta"],DATE_ONLY=/^\d{4}-\d{2}-\d{2}$/,pad2=t=>t<10?`0${t}`:`${t}`,emptyOf=t=>t??(0,_formatConfig.getFormatterConfig)().empty,toInstant=t=>{if(null==t||""===t)return null;const e=t instanceof Date?t:new Date("string"==typeof t?t.trim():t);return Number.isNaN(e.getTime())?null:e},isDateOnly=t=>"string"==typeof t&&DATE_ONLY.test(t.trim()),gmtLabel=t=>{if(0===t)return"GMT";const e=t>0?"+":"-",
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatTime=exports.formatRelative=exports.formatPercent=exports.formatNumber=exports.formatMinor=exports.formatDateTime=exports.formatDate=void 0;var _formatConfig=require("./formatConfig.js"),_intlCache=require("./intlCache.js");const MONTHS=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],IST_OFFSET_MINUTES=330,IST_NAMES=["IST","Asia/Kolkata","Asia/Calcutta"],DATE_ONLY=/^\d{4}-\d{2}-\d{2}$/,pad2=t=>t<10?`0${t}`:`${t}`,emptyOf=t=>t??(0,_formatConfig.getFormatterConfig)().empty,toInstant=t=>{if(null==t||""===t)return null;const e=t instanceof Date?t:new Date("string"==typeof t?t.trim():t);return Number.isNaN(e.getTime())?null:e},isDateOnly=t=>"string"==typeof t&&DATE_ONLY.test(t.trim()),gmtLabel=t=>{if(0===t)return"GMT";const e=t>0?"+":"-",r=Math.abs(t),n=r%60;return`GMT${e}${Math.floor(r/60)}${0===n?"":`:${pad2(n)}`}`},shifted=(t,e,r)=>{const n=new Date(t.getTime()+6e4*e);return{year:n.getUTCFullYear(),month:n.getUTCMonth(),day:n.getUTCDate(),hour:n.getUTCHours(),minute:n.getUTCMinutes(),label:r}},inIanaZone=(t,e)=>{const r=(0,_intlCache.dateTimeFormat)("en-US",{timeZone:e,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",hour12:!1}).formatToParts(t),read=t=>Number.parseInt(r.find(e=>e.type===t)?.value??"",10),n=read("year"),o=read("month")-1,i=read("day"),a=read("hour")%24,m=read("minute"),l=Date.UTC(n,o,i,a,m),u=Math.round((l-6e4*Math.floor(t.getTime()/6e4))/6e4);return{year:n,month:o,day:i,hour:a,minute:m,label:gmtLabel(u)}},wallClock=(t,e)=>IST_NAMES.includes(e)?shifted(t,330,"IST"):"UTC"===e?shifted(t,0,"UTC"):"viewer"===e?{year:t.getFullYear(),month:t.getMonth(),day:t.getDate(),hour:t.getHours(),minute:t.getMinutes(),label:gmtLabel(-t.getTimezoneOffset())}:inIanaZone(t,e),hourCycleOf=t=>t.hourCycle??12,dayMonthYear=t=>`${pad2(t.day)}-${MONTHS[t.month]}-${t.year}`,numericDate=(t,e)=>{const r=pad2(t.day),n=pad2(t.month+1),o=String(t.year).padStart(4,"0");return"DayMonthYear"===e?`${r}/${n}/${o}`:"MonthDayYear"===e?`${n}/${r}/${o}`:`${o}-${n}-${r}`},clockTime=(t,e)=>24===e?`${pad2(t.hour)}:${pad2(t.minute)}`:`${t.hour%12||12}:${pad2(t.minute)} ${t.hour<12?"AM":"PM"}`,labelled=(t,e)=>e??!IST_NAMES.includes(t),withLabel=(t,e,r,n)=>labelled(r,n)?`${t} ${e.label}`:t,intlZone=t=>{if("viewer"!==t)return IST_NAMES.includes(t)?"Asia/Kolkata":t},localeDayMonthYear=(t,e,r)=>{const n=(0,_intlCache.dateTimeFormat)(e,{day:"2-digit",month:"short",year:"numeric",timeZone:r}).formatToParts(t),part=t=>n.find(e=>e.type===t)?.value??"";return`${part("day")}-${part("month").replace(".","")}-${part("year")}`},dateText=(t,e)=>{const r=(0,_formatConfig.getFormatterConfig)().dateOrder??"DayMonthNameYear";if("DayMonthNameYear"!==r)return numericDate(wallClock(t,e),r);const n=(0,_formatConfig.configuredLocale)();return n?localeDayMonthYear(t,n,intlZone(e)):dayMonthYear(wallClock(t,e))},localeClock=(t,e,r,n)=>(0,_intlCache.dateTimeFormat)(e,{hour:"2-digit",minute:"2-digit",timeZone:intlZone(r),timeZoneName:labelled(r,n.zoneLabel)?"short":void 0,hourCycle:void 0===n.hourCycle?void 0:24===n.hourCycle?"h23":"h12"}).format(t),formatDate=(t,e={})=>{const r=toInstant(t);return r?dateText(r,isDateOnly(t)?"UTC":e.zone??(0,_formatConfig.getFormatterConfig)().zone):emptyOf(e.empty)};exports.formatDate=formatDate;const formatTime=(t,e={})=>{const r=toInstant(t);if(!r)return emptyOf(e.empty);const n=e.zone??(0,_formatConfig.getFormatterConfig)().zone,o=(0,_formatConfig.configuredLocale)();if(o)return localeClock(r,o,n,e);const i=wallClock(r,n);return withLabel(clockTime(i,hourCycleOf(e)),i,n,e.zoneLabel)};exports.formatTime=formatTime;const formatDateTime=(t,e={})=>{const r=toInstant(t);if(!r)return emptyOf(e.empty);const n=e.zone??(0,_formatConfig.getFormatterConfig)().zone,o=(0,_formatConfig.configuredLocale)();if(o)return`${dateText(r,n)}, ${localeClock(r,o,n,e)}`;const i=wallClock(r,n);return withLabel(`${dateText(r,n)}, ${clockTime(i,hourCycleOf(e))}`,i,n,e.zoneLabel)};exports.formatDateTime=formatDateTime;const SECOND=1e3,MINUTE=6e4,HOUR=36e5,DAY=24*HOUR,WEEK=7*DAY,MONTH=30*DAY,YEAR=365*DAY,INTL_UNITS=[["year",YEAR],["month",MONTH],["day",DAY],["hour",HOUR],["minute",6e4]],formatRelative=(t,e={})=>{const r=toInstant(t),n=toInstant(e.now??Date.now());if(!r||!n)return emptyOf(e.empty);const o=r.getTime()-n.getTime(),i=Math.abs(o),a=Intl.RelativeTimeFormat,m=(0,_formatConfig.configuredLocale)();if((null!==m||!0===e.intl)&&"function"==typeof a){const t=(0,_intlCache.relativeTimeFormat)(a,m??(0,_formatConfig.getFormatterConfig)().locale),[e,r]=INTL_UNITS.find(([,t])=>i>=t)??["second",1e3];return t.format(Math.round(o/r),e)}if(i<6e4)return"just now";const[l,u]=i<HOUR?["minute",6e4]:i<DAY?["hour",HOUR]:i<WEEK?["day",DAY]:i<MONTH?["week",WEEK]:i<YEAR?["month",MONTH]:["year",YEAR],c=Math.floor(i/u),s=`${c} ${l}${1===c?"":"s"}`;return o<0?`${s} ago`:`in ${s}`};exports.formatRelative=formatRelative;const toNumber=t=>{if(null==t)return null;if("string"==typeof t&&""===t.trim())return null;const e="number"==typeof t?t:Number(t);return Number.isFinite(e)?e:null},clampDigits=t=>Math.min(20,Math.max(0,Math.trunc(t))),shiftDecimal=(t,e)=>/e/i.test(String(t))?t*10**e:Number(`${t}e${e}`),houseSeparators=()=>(0,_formatConfig.numberSeparators)()??{decimal:".",group:","},groupInteger=(t,e,r)=>{if("none"===e||t.length<=3)return t;if("international"===e)return t.replace(/\B(?=(\d{3})+(?!\d))/g,r);return`${t.slice(0,-3).replace(/\B(?=(\d{2})+(?!\d))/g,r)}${r}${t.slice(-3)}`},hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,plainDigits=(t,e)=>{if(hasIntlNumber())return(0,_intlCache.numberFormat)("en-US",{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:e}).format(t);const r=Math.min(e,15);return shiftDecimal(Math.round(shiftDecimal(t,r)),-r).toFixed(r)},decimalText=(t,e,r,n)=>{const o=Math.max(clampDigits(r),clampDigits(e)),i=clampDigits(e),a=plainDigits(Math.abs(t),o),[m="0",l=""]=a.split(".");let u=l.padEnd(i,"0");for(;u.length>i&&u.endsWith("0");)u=u.slice(0,-1);const c=houseSeparators(),s=groupInteger(m,n,c.group)+(u?`${c.decimal}${u}`:"");return t<0&&/[1-9]/.test(a)?`-${s}`:s},HOUSE_NUMBER_KEYS=new Set(["grouping","minimumFractionDigits","maximumFractionDigits","locale","empty","scale"]),intlNumberOptions=t=>{if(!Object.entries(t).some(([t,e])=>void 0!==e&&!HOUSE_NUMBER_KEYS.has(t)))return null;const{grouping:e,locale:r,empty:n,scale:o,...i}=t;return"none"===e&&void 0===i.useGrouping?{...i,useGrouping:!1}:i},localeOf=t=>t.locale??(0,_formatConfig.getFormatterConfig)().locale,intlTextLocale=t=>{const e=(0,_formatConfig.configuredLocale)();return null===e||"indian"===t.grouping||"international"===t.grouping?null:t.locale??e},fractionDigits=(t,e)=>{const r=clampDigits(t);return{minimumFractionDigits:r,maximumFractionDigits:Math.max(r,clampDigits(e))}},groupingOption=t=>"none"===t?{useGrouping:!1}:{},formatNumber=(t,e={})=>{const r=toNumber(t);if(null===r)return emptyOf(e.empty);const n=intlNumberOptions(e);if(n)return(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(localeOf(e),n),r);const o=intlTextLocale(e);return o?(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(o,{...fractionDigits(e.minimumFractionDigits??0,e.maximumFractionDigits??3),...groupingOption(e.grouping)}),r):decimalText(r,e.minimumFractionDigits??0,e.maximumFractionDigits??3,e.grouping??(0,_formatConfig.groupingForLocale)(localeOf(e)))};exports.formatNumber=formatNumber;const formatPercent=(t,e={})=>{const r=toNumber(t);if(null===r)return emptyOf(e.empty);const n=intlNumberOptions(e);if(n){const t="percent"===e.scale?shiftDecimal(r,-2):r;return(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(localeOf(e),{style:"percent",...n}),t)}const o=intlTextLocale(e);if(o){const t="percent"===e.scale?shiftDecimal(r,-2):r;return(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(o,{style:"percent",...fractionDigits(e.minimumFractionDigits??0,e.maximumFractionDigits??e.minimumFractionDigits??0),...groupingOption(e.grouping)}),t)}const i="percent"===e.scale?r:shiftDecimal(r,2);return`${decimalText(i,e.minimumFractionDigits??0,e.maximumFractionDigits??e.minimumFractionDigits??0,e.grouping??(0,_formatConfig.groupingForLocale)(localeOf(e)))}%`};exports.formatPercent=formatPercent;const SYMBOLS={INR:"₹",USD:"$",EUR:"€",GBP:"£"},MINOR_DIGITS={JPY:0,KRW:0,VND:0,BHD:3,JOD:3,KWD:3,OMR:3,TND:3},formatMinor=(t,e={})=>{const r=toNumber(t);if(null===r)return emptyOf(e.empty);const n=(e.currency??"INR").toUpperCase(),o=MINOR_DIGITS[n]??2,i=Math.round(Math.abs(r)),a=String(i).padStart(o+1,"0"),m=a.slice(0,a.length-o);let l=a.slice(a.length-o);e.dropZeroDecimals&&/^0*$/.test(l)&&(l="");const u=intlTextLocale({grouping:e.grouping});if(u)try{const t=Number(`${r<0&&0!==i?"-":""}${m}.${a.slice(a.length-o)||"0"}`);return(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(u,{...!1===e.symbol?{}:{style:"currency",currency:n},...fractionDigits(l?o:0,o),...groupingOption(e.grouping)}),t)}catch{}const c=e.grouping??("INR"===n?"indian":"international"),s=houseSeparators(),f=groupInteger(m,c,s.group)+(l?`${s.decimal}${l}`:""),g=r<0&&0!==i?"-":"";if(!1===e.symbol)return`${g}${f}`;const p=SYMBOLS[n];return p?`${g}${p}${f}`:`${g}${n} ${f}`};exports.formatMinor=formatMinor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatCompactNumber=void 0,exports.formatNumber=formatNumber,exports.formatPercent=formatPercent;var _house=require("./house.js"),_intlCache=require("./intlCache.js");const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat;function formatNumber(t,e,r){if("number"!=typeof e&&void 0===r)return(0,_house.formatNumber)(t,e);const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatCompactNumber=void 0,exports.formatNumber=formatNumber,exports.formatPercent=formatPercent;var _formatConfig=require("./formatConfig.js"),_house=require("./house.js"),_intlCache=require("./intlCache.js");const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,withDecimalMark=t=>{const e=(0,_formatConfig.numberSeparators)();return null===e?t:t.replace(".",e.decimal)};function formatNumber(t,e,r){if("number"!=typeof e&&void 0===r)return(0,_house.formatNumber)(t,e);const i="number"==typeof e?e:void 0,o=t;if(null==o||Number.isNaN(o))return"";if(hasIntlNumber())try{const t={};return null!=i&&(t.minimumFractionDigits=i,t.maximumFractionDigits=i),(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(r??"en-IN",t),o)}catch{}return withDecimalMark(null!=i?o.toFixed(i):String(o))}function formatPercent(t,e,r,i){if("number"!=typeof e&&void 0===r&&void 0===i)return(0,_house.formatPercent)(t,e);const o="number"==typeof e?e:0,n=t;if(null==n||Number.isNaN(n))return"";const m=r??1?n:n/100;if(hasIntlNumber())try{return(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(i??"en-IN",{style:"percent",minimumFractionDigits:o,maximumFractionDigits:o}),m)}catch{}return`${withDecimalMark((100*m).toFixed(o))}%`}const formatCompactNumber=(t,e="en-IN")=>{if(null==t||Number.isNaN(t))return"";if(hasIntlNumber())try{return(0,_formatConfig.styledNumber)((0,_intlCache.numberFormat)(e,{notation:"compact",maximumFractionDigits:1}),t)}catch{}const r=Math.abs(t),i=t<0?"-":"";return r>=1e7?`${i}${withDecimalMark((r/1e7).toFixed(1))}Cr`:r>=1e5?`${i}${withDecimalMark((r/1e5).toFixed(1))}L`:r>=1e3?`${i}${withDecimalMark((r/1e3).toFixed(1))}K`:withDecimalMark(`${t}`)};exports.formatCompactNumber=formatCompactNumber;
|
|
@@ -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:"[0m",GRAY:"[90m",BLUE:"[34m",YELLOW:"[33m",RED_BOLD:"[31;1m"},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{}},toErrorObject=e=>{if(e instanceof Error)return e;if("string"==typeof e)return new Error(e);try{return new Error(JSON.stringify(e))}catch{return new Error(String(e))}};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};let loggerOptions={...DEFAULT_LOGGER_OPTIONS};const configureLogger=e=>{loggerOptions={...loggerOptions,...e},screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit))};exports.configureLogger=configureLogger;let currentScreen=null,screenHistory=[];const 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=t[0];void 0===s||(0,_extractApiError.isNoResponse)(r[0])||forwardErrorToRemote(toErrorObject(s),{source:"Logger.error",message:o})},breadcrumb=(e,r)=>{const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);isEnabled()&&isLogLevelAllowed("info")&&console.info(`${Colors.BLUE}[BREADCRUMB]: ${o}${Colors.RESET}`,t??""),safe(()=>remote?.breadcrumb?.(o,t))},recordError=(e,r)=>{const o=(0,_redact.redact)(toErrorObject(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(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((0,_redact.redact)(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],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};
|
|
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:"[0m",GRAY:"[90m",BLUE:"[34m",YELLOW:"[33m",RED_BOLD:"[31;1m"},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{}},toErrorObject=e=>{if(e instanceof Error)return e;if("string"==typeof e)return new Error(e);try{return new Error(JSON.stringify(e))}catch{return new Error(String(e))}};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};let loggerOptions={...DEFAULT_LOGGER_OPTIONS};const configureLogger=e=>{loggerOptions={...loggerOptions,...e},screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit))};exports.configureLogger=configureLogger;let currentScreen=null,screenHistory=[];const 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=t[0];void 0===s||(0,_extractApiError.isNoResponse)(r[0])||forwardErrorToRemote(toErrorObject(s),{source:"Logger.error",message:o})},breadcrumb=(e,r)=>{const o=(0,_redact.redactString)(e),t=(0,_redact.redact)(r);isEnabled()&&isLogLevelAllowed("info")&&console.info(`${Colors.BLUE}[BREADCRUMB]: ${o}${Colors.RESET}`,t??""),safe(()=>remote?.breadcrumb?.(o,t))},recordError=(e,r)=>{const o=(0,_redact.redact)(toErrorObject(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((0,_redact.redact)(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],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};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.setPermissionsImplementation=exports.registerPermissionAdapter=exports.Permissions=void 0;var _reactNative=require("react-native"),_index=require("../logger/index.js");let backend=null;const setPermissionsImplementation=e=>{backend=e};exports.setPermissionsImplementation=setPermissionsImplementation;const registry=new Map,registerPermissionAdapter=(e,
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.setPermissionsImplementation=exports.registerPermissionAdapter=exports.Permissions=void 0;var _reactNative=require("react-native"),_index=require("../logger/index.js");let backend=null;const setPermissionsImplementation=e=>{backend=e};exports.setPermissionsImplementation=setPermissionsImplementation;const registry=new Map,registerPermissionAdapter=(e,r)=>{registry.set(e,r)};exports.registerPermissionAdapter=registerPermissionAdapter;const resolveExpoModule=e=>registry.get(e)??null,toStatus=e=>e?"limited"===e.accessPrivileges?"limited":"granted"===e.status?"granted":"denied"===e.status?e.canAskAgain?"denied":"blocked":"undetermined":"unavailable",checkPermission=async e=>{if(backend)return backend.check(e);const r=resolveExpoModule(e);if(!r)return"unavailable";try{return toStatus(await r.check())}catch(r){return _index.Logger.error(`[permissions] check(${e}) failed`,r),"unavailable"}},requestPermission=async e=>{if(backend)return backend.request(e);const r=resolveExpoModule(e);if(!r)return"unavailable";try{return toStatus(await r.request())}catch(r){return _index.Logger.error(`[permissions] request(${e}) failed`,r),"unavailable"}},openAppSettings=async()=>{try{return await _reactNative.Linking.openSettings(),!0}catch(e){return _index.Logger.error("[permissions] openAppSettings failed",e),!1}},Permissions=exports.Permissions={check:checkPermission,request:requestPermission,isAuthorized:async e=>{const r=await checkPermission(e);return"granted"===r||"limited"===r},ensure:async e=>{const r=await checkPermission(e);return"undetermined"===r||"denied"===r?requestPermission(e):r},openSettings:openAppSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.usePush=exports.toPushReceived=exports.toPushAction=exports.toNotificationActions=exports.setPushImplementation=exports.setCategories=exports.setBadgeCount=exports.routeTaskPayload=exports.resolveModules=exports.resetPush=exports.onReceive=exports.onAction=exports.notifyLocal=exports.initPush=exports.enablePush=exports.disablePush=void 0;var _react=require("react"),_reactNative=require("react-native"),_index=require("../logger/index.js");let resolved,override=null;const setPushImplementation=e=>{override=e};exports.setPushImplementation=setPushImplementation;const resolveModules=()=>{if(override)return override;if(void 0!==resolved)return resolved;try{if(require("expo").isRunningInExpoGo())return resolved=null,resolved;const e=require("expo-notifications"),t=require("expo-application");resolved={notifications:e,applicationId:t.applicationId,getApnsEnvironment:()=>t.getIosPushNotificationServiceEnvironmentAsync()}}catch(e){_index.Logger.warn("[push] expo-notifications is not available; push is off",e),resolved=null}return resolved};exports.resolveModules=resolveModules;let state={status:"unknown",enabled:!1};const subscribers=new Set,setState=e=>{state={...state,...e};for(const e of subscribers)e()};let config=null,channelsReady=Promise.resolve(),tokenSubscription=null,actionHandler=null;const receiveHandlers=new Set;let listening=!1,listeningForReceived=!1;const pendingResponses=[],routedAt=new Map,REPEAT_WINDOW_MS=1e4,requireConfig=()=>{if(!config)throw new Error("[@webority/mobile-core] call initPush before enablePush or disablePush.");return config},toPermissionStatus=e=>e.granted?"granted":"denied"===e.status?"denied":"
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.usePush=exports.toPushReceived=exports.toPushAction=exports.toNotificationActions=exports.setPushImplementation=exports.setCategories=exports.setBadgeCount=exports.routeTaskPayload=exports.resolveModules=exports.resetPush=exports.onReceive=exports.onAction=exports.notifyLocal=exports.initPush=exports.enablePush=exports.disablePush=void 0;var _react=require("react"),_reactNative=require("react-native"),_index=require("../logger/index.js");let resolved,override=null;const setPushImplementation=e=>{override=e};exports.setPushImplementation=setPushImplementation;const resolveModules=()=>{if(override)return override;if(void 0!==resolved)return resolved;try{if(require("expo").isRunningInExpoGo())return resolved=null,resolved;const e=require("expo-notifications"),t=require("expo-application");resolved={notifications:e,applicationId:t.applicationId,getApnsEnvironment:()=>t.getIosPushNotificationServiceEnvironmentAsync()}}catch(e){_index.Logger.warn("[push] expo-notifications is not available; push is off",e),resolved=null}return resolved};exports.resolveModules=resolveModules;let state={status:"unknown",enabled:!1};const subscribers=new Set,setState=e=>{state={...state,...e};for(const e of subscribers)e()};let config=null,channelsReady=Promise.resolve(),tokenSubscription=null,actionHandler=null;const receiveHandlers=new Set;let listening=!1,listeningForReceived=!1;const pendingResponses=[],routedAt=new Map,REPEAT_WINDOW_MS=1e4,requireConfig=()=>{if(!config)throw new Error("[@webority/mobile-core] call initPush before enablePush or disablePush.");return config},toPermissionStatus=e=>e.granted?"granted":"denied"===e.status?e.canAskAgain?"denied":"blocked":"undetermined",toStringData=e=>{const t={};for(const[n,o]of Object.entries(e??{}))null!=o&&(t[n]="object"==typeof o?JSON.stringify(o):String(o));return t},contentData=e=>{const t=e.request.content;if(t.data)return toStringData(t.data);if("string"==typeof t.dataString)try{return toStringData(JSON.parse(t.dataString))}catch(e){_index.Logger.error("[push] notification data is not JSON",e)}return{}},triggerData=e=>{const t=e.request.trigger,n={...t?.remoteMessage?.data??{}};for(const[e,o]of Object.entries(t?.payload??{}))"aps"===e||"body"===e&&"object"==typeof o||(n[e]=o);return toStringData(n)},notificationData=e=>({...triggerData(e),...contentData(e)}),responseData=e=>notificationData(e.notification),toPushReceived=e=>({notificationId:e.request.identifier,title:e.request.content.title??null,body:e.request.content.body??null,data:notificationData(e)});exports.toPushReceived=toPushReceived;const toPushAction=e=>({actionId:e.actionIdentifier,...e.userText?{userText:e.userText}:{},data:responseData(e),notificationId:e.notification.request.identifier});exports.toPushAction=toPushAction;const toNotificationActions=e=>e.map(e=>({identifier:e.id,buttonTitle:e.title,...e.textInput?{textInput:{submitButtonTitle:e.textInput.submitTitle,placeholder:e.textInput.placeholder}}:{},options:{opensAppToForeground:e.opensApp??!0,isDestructive:e.destructive??!1,isAuthenticationRequired:e.authenticationRequired??!1}}));exports.toNotificationActions=toNotificationActions;const routeResponse=async(e,t)=>{const n=`${t.notification.request.identifier}:${t.actionIdentifier}`,o=routedAt.get(n);if(void 0!==o&&Date.now()-o<1e4)return;if(t.actionIdentifier!==e.DEFAULT_ACTION_IDENTIFIER&&actionHandler){routedAt.set(n,Date.now());try{await actionHandler(toPushAction(t))}catch(e){_index.Logger.error("[push] onAction threw",e)}}else if(config){routedAt.set(n,Date.now());try{config.onOpen(responseData(t))}catch(e){_index.Logger.error("[push] onOpen threw",e)}}else pendingResponses.push(t)},drainPending=async e=>{const t=pendingResponses.splice(0);for(const n of t)await routeResponse(e,n)},listenForResponses=e=>{listening||(listening=!0,e.addNotificationResponseReceivedListener(t=>{routeResponse(e,t)}),e.getLastNotificationResponseAsync().then(async t=>(t&&await routeResponse(e,t),e.clearLastNotificationResponseAsync?.())).catch(e=>_index.Logger.error("[push] reading the launch notification failed",e)))},routeTaskPayload=async e=>{const t=resolveModules(),n=e;t&&"string"==typeof n?.actionIdentifier&&"string"==typeof n.notification?.request?.identifier&&await routeResponse(t.notifications,n)};exports.routeTaskPayload=routeTaskPayload;const createChannels=async(e,t)=>{for(const n of t)try{await e.setNotificationChannelAsync(n.id,{name:n.name,importance:"high"===n.importance?e.AndroidImportance.HIGH:e.AndroidImportance.DEFAULT})}catch(e){_index.Logger.error(`[push] creating channel ${n.id} failed`,e)}},APNS_ENVIRONMENTS={development:"Development",production:"Production"},readApnsEnvironment=async e=>{try{return APNS_ENVIRONMENTS[await e.getApnsEnvironment()??""]??null}catch(e){return _index.Logger.warn("[push] reading the APNs environment failed",e),null}},toDevice=async(e,t)=>{const n="android"===e.type?"Fcm":"ios"===e.type?"Apns":null;if(!n||"string"!=typeof e.data)return null;if(!t.applicationId)throw new Error("[@webority/mobile-core] push needs the app bundle id from expo-application.");return{installationId:await requireConfig().getInstallationId(),platform:n,token:e.data,appId:t.applicationId,apnsEnvironment:"Apns"===n?await readApnsEnvironment(t):null}},initPush=e=>{const t=null===config;if(config=e,!t)return;const n=resolveModules();if(!n)return void setState({status:"unavailable"});const o=n.notifications;o.setNotificationHandler({handleNotification:async()=>{const e=config?.showInForeground?.()??!0;return{shouldShowBanner:e,shouldShowList:e,shouldPlaySound:e&&(config?.playSoundInForeground?.()??!0),shouldSetBadge:!0}}}),"android"===_reactNative.Platform.OS&&e.androidChannels?.length&&(channelsReady=createChannels(o,e.androidChannels)),listenForResponses(o),drainPending(o),o.getPermissionsAsync().then(e=>setState({status:toPermissionStatus(e)})).catch(e=>_index.Logger.error("[push] permission check failed",e))};exports.initPush=initPush;let registering=null,registeredKey=null,unregistering=null,tokenDrop=Promise.resolve();const registerOnce=e=>{const t=JSON.stringify(e);if(registering?.key===t)return registering.promise;const n=requireConfig().register(e).then(()=>{registeredKey=t}).finally(()=>{registering?.promise===n&&(registering=null)});return registering={key:t,promise:n},n},enablePush=async({prompt:e=!0}={})=>{requireConfig();const t=resolveModules();if(!t)return setState({status:"unavailable"}),"unavailable";const n=t.notifications;await channelsReady,await tokenDrop;let o=await n.getPermissionsAsync();if(!o.granted&&e&&(o=await n.requestPermissionsAsync()),!o.granted){const e=toPermissionStatus(o);return setState({status:e}),e}const i=await toDevice(await n.getDevicePushTokenAsync(),t);return i?(await registerOnce(i),tokenSubscription?.remove(),tokenSubscription=n.addPushTokenListener(e=>{(unregistering??Promise.resolve()).then(()=>state.enabled?toDevice(e,t):null).then(e=>e&&JSON.stringify(e)!==registeredKey?registerOnce(e):void 0).catch(e=>_index.Logger.error("[push] re-registering a new token failed",e))}),setState({status:"granted",enabled:!0}),"granted"):(setState({status:"unavailable"}),"unavailable")};exports.enablePush=enablePush;const stopFollowingToken=()=>{tokenSubscription?.remove(),tokenSubscription=null,registeredKey=null,setState({enabled:!1})},disablePush=async()=>{const e=requireConfig(),t=await e.getInstallationId();await(registering?.promise.catch(()=>{}));let settle=()=>{};const n=new Promise(e=>{settle=e});unregistering=n;try{await e.unregister(t),stopFollowingToken()}finally{unregistering===n&&(unregistering=null),settle()}};exports.disablePush=disablePush;const resetPush=async()=>{stopFollowingToken();const e=resolveModules();if(!e)return;const t=e.notifications.unregisterForNotificationsAsync();tokenDrop=t.catch(()=>{}),await t};exports.resetPush=resetPush;const setBadgeCount=async e=>{const t=resolveModules();t&&await t.notifications.setBadgeCountAsync(e)};exports.setBadgeCount=setBadgeCount;const setCategories=async e=>{const t=resolveModules();if(t)for(const n of e)await t.notifications.setNotificationCategoryAsync(n.id,toNotificationActions(n.actions))};exports.setCategories=setCategories;const onAction=e=>{actionHandler=e;const t=resolveModules();return t&&(listenForResponses(t.notifications),drainPending(t.notifications)),()=>{actionHandler===e&&(actionHandler=null)}};exports.onAction=onAction;const onReceive=e=>{receiveHandlers.add(e);const t=resolveModules();return t&&!listeningForReceived&&(listeningForReceived=!0,t.notifications.addNotificationReceivedListener(e=>{const t=toPushReceived(e);for(const e of[...receiveHandlers])try{e(t)}catch(e){_index.Logger.error("[push] onReceive threw",e)}})),()=>{receiveHandlers.delete(e)}};exports.onReceive=onReceive;const notifyLocal=async({title:e,body:t,data:n})=>{const o=resolveModules();o&&await o.notifications.scheduleNotificationAsync({content:{title:e,body:t,data:n??{}},trigger:null})};exports.notifyLocal=notifyLocal;const subscribe=e=>(subscribers.add(e),()=>{subscribers.delete(e)}),getSnapshot=()=>state,enable=async()=>{await enablePush()},usePush=()=>({...(0,_react.useSyncExternalStore)(subscribe,getSnapshot,getSnapshot),enable:enable,disable:disablePush});exports.usePush=usePush;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.PUSH_STATUS=void 0;const PUSH_STATUS=exports.PUSH_STATUS={unknown:"unknown",granted:"granted",denied:"denied",unavailable:"unavailable"};
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.PUSH_STATUS=void 0;const PUSH_STATUS=exports.PUSH_STATUS={unknown:"unknown",undetermined:"undetermined",granted:"granted",denied:"denied",blocked:"blocked",unavailable:"unavailable"};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import axios,{AxiosHeaders}from"axios";import{ACCESS_TOKEN_KEY,getToken}from"../auth/authStore.js";import{getConfigValue}from"../config/index.js";import{Logger}from"../logger/index.js";import{getLastKnownNetworkStatus}from"../network/networkStatus.js";import"../types/axios.js";import{applyConfiguredBaseUrl}from"./baseUrl.js";import{applyClientHeaders,readAccountId,stampAccountId}from"./clientHeaders.js";import{logCurl}from"./curl.js";import{readMinAppVersion}from"./minAppVersion.js";import{sendFormDataAsMultipart}from"./multipart.js";import{applyRequestDefaults}from"./requestDefaults.js";import{responseBodyText}from"./responseBodyText.js";import{attachRetry}from"./retry.js";import{beginSessionReplacement,currentTokenIfReplaced,endSessionAndLogout,getAccountIdProvider,getErrorMessage,getRefreshPath,isRefreshInFlight,queueBehindRefresh,readSignOutReason,refreshAccessToken,resetRefreshState,storeReplacementSession,waitForSessionReplacement}from"./tokenRefresh.js";import{isWorkspaceChangedResponse,WorkspaceChangedError}from"./workspace.js";export{injectStore,injectUserAuth,resetRefreshState,SIGN_OUT_REASON_HEADER}from"./tokenRefresh.js";export class RequestOfflineError extends Error{constructor(e="Request blocked: device is offline"){super(e),this.name="RequestOfflineError",Object.setPrototypeOf(this,RequestOfflineError.prototype)}}class NoAccessTokenError extends Error{constructor(){super("No access token available"),this.name="NoAccessTokenError",Object.setPrototypeOf(this,NoAccessTokenError.prototype)}}export const SESSION_TERMINATION_CODES={TERMINATED:"SESSION_TERMINATED",EXPIRED:"SESSION_EXPIRED"};const TERMINATION_CODES=new Set(Object.values(SESSION_TERMINATION_CODES));export const SESSION_INVALID_HEADER="x-security-stamp-invalid";const hasSessionInvalidHeader=e=>{if(!e||"object"!=typeof e)return!1;const r=e.get,t="function"==typeof r?r.call(e,SESSION_INVALID_HEADER):e[SESSION_INVALID_HEADER];return"true"===String(t).toLowerCase()},getSessionTerminationCode=e=>{if(!e||"object"!=typeof e)return;const r=e,t=r.error,s=[r.code,r.errorCode,t&&"object"==typeof t?t.code:void 0];for(const e of s)if("string"==typeof e&&TERMINATION_CODES.has(e))return e},endReplacement=e=>{e?._endReplacement?.(),e&&(e._endReplacement=void 0)},readSentToken=e=>{const r=e.headers instanceof AxiosHeaders?e.headers.get("Authorization"):void 0;return"string"==typeof r&&r.startsWith("Bearer ")?r.slice(7):null},userClient=axios.create({headers:{"Content-Type":"application/json"}});readMinAppVersion(userClient),attachRetry(userClient);const setAuthHeader=(e,r)=>{e.headers instanceof AxiosHeaders?e.headers.set("Authorization",`Bearer ${r}`):e.headers=AxiosHeaders.from({...e.headers,Authorization:`Bearer ${r}`})},isRefreshTokenRequest=e=>{const r=getRefreshPath();return!!r&&!!e?.includes(r)};userClient.interceptors.request.use(e=>(e.replacesSession&&!isRefreshTokenRequest(e.url)
|
|
1
|
+
"use strict";import axios,{AxiosHeaders}from"axios";import{ACCESS_TOKEN_KEY,getToken}from"../auth/authStore.js";import{getConfigValue}from"../config/index.js";import{Logger}from"../logger/index.js";import{getLastKnownNetworkStatus}from"../network/networkStatus.js";import"../types/axios.js";import{applyConfiguredBaseUrl}from"./baseUrl.js";import{applyClientHeaders,readAccountId,stampAccountId}from"./clientHeaders.js";import{logCurl}from"./curl.js";import{readMinAppVersion}from"./minAppVersion.js";import{sendFormDataAsMultipart}from"./multipart.js";import{applyRequestDefaults}from"./requestDefaults.js";import{responseBodyText}from"./responseBodyText.js";import{attachRetry}from"./retry.js";import{beginSessionReplacement,currentTokenIfReplaced,endSessionAndLogout,getAccountIdProvider,getErrorMessage,getRefreshPath,isRefreshInFlight,queueBehindRefresh,readSignOutReason,refreshAccessToken,resetRefreshState,storeReplacementSession,waitForSessionReplacement}from"./tokenRefresh.js";import{isWorkspaceChangedResponse,WorkspaceChangedError}from"./workspace.js";export{injectStore,injectUserAuth,resetRefreshState,SIGN_OUT_REASON_HEADER}from"./tokenRefresh.js";export class RequestOfflineError extends Error{constructor(e="Request blocked: device is offline"){super(e),this.name="RequestOfflineError",Object.setPrototypeOf(this,RequestOfflineError.prototype)}}class NoAccessTokenError extends Error{constructor(){super("No access token available"),this.name="NoAccessTokenError",Object.setPrototypeOf(this,NoAccessTokenError.prototype)}}export const SESSION_TERMINATION_CODES={TERMINATED:"SESSION_TERMINATED",EXPIRED:"SESSION_EXPIRED"};const TERMINATION_CODES=new Set(Object.values(SESSION_TERMINATION_CODES));export const SESSION_INVALID_HEADER="x-security-stamp-invalid";const hasSessionInvalidHeader=e=>{if(!e||"object"!=typeof e)return!1;const r=e.get,t="function"==typeof r?r.call(e,SESSION_INVALID_HEADER):e[SESSION_INVALID_HEADER];return"true"===String(t).toLowerCase()},getSessionTerminationCode=e=>{if(!e||"object"!=typeof e)return;const r=e,t=r.error,s=[r.code,r.errorCode,t&&"object"==typeof t?t.code:void 0];for(const e of s)if("string"==typeof e&&TERMINATION_CODES.has(e))return e},endReplacement=e=>{e?._endReplacement?.(),e&&(e._endReplacement=void 0)},closeWindowIfTransformThrows=e=>{if(e._transformGuarded)return;e._transformGuarded=!0;const r=[].concat(e.transformRequest??[]);e.transformRequest=[function guarded(e,t){try{return r.reduce((e,r)=>r.call(this,e,t),e)}catch(e){throw endReplacement(this),e}}]},readSentToken=e=>{const r=e.headers instanceof AxiosHeaders?e.headers.get("Authorization"):void 0;return"string"==typeof r&&r.startsWith("Bearer ")?r.slice(7):null},userClient=axios.create({headers:{"Content-Type":"application/json"}});readMinAppVersion(userClient),attachRetry(userClient);const setAuthHeader=(e,r)=>{e.headers instanceof AxiosHeaders?e.headers.set("Authorization",`Bearer ${r}`):e.headers=AxiosHeaders.from({...e.headers,Authorization:`Bearer ${r}`})},isRefreshTokenRequest=e=>{const r=getRefreshPath();return!!r&&!!e?.includes(r)};userClient.interceptors.request.use(e=>{if(e.replacesSession&&!isRefreshTokenRequest(e.url)){const r=e;r._endReplacement=beginSessionReplacement(),closeWindowIfTransformThrows(r)}return e}),applyConfiguredBaseUrl(userClient),applyRequestDefaults(userClient),sendFormDataAsMultipart(userClient),userClient.interceptors.request.use(e=>(getConfigValue("logCurl")&&logCurl(e),e)),applyClientHeaders(userClient),userClient.interceptors.request.use(async e=>{endReplacement(e);if(!1===(await getLastKnownNetworkStatus()).isConnected)return Logger.warn(`Request blocked: device is offline. URL: ${e.url}`),Promise.reject(new RequestOfflineError);try{if(isRefreshTokenRequest(e.url))return e;await stampAccountId(e,getAccountIdProvider());const r=await getToken(ACCESS_TOKEN_KEY);if(!r?.token)throw new NoAccessTokenError;const t=Date.now(),s=Date.parse(r.expiry);if(s<=t+3e4){Logger.info("Access token expired or about to expire, refreshing before request");const r=await refreshAccessToken();setAuthHeader(e,r)}else setAuthHeader(e,r.token);return e}catch(r){return r instanceof NoAccessTokenError?Logger.info(`Request not sent: signed out. URL: ${e.url}`):Logger.error("Failed to attach token:",getErrorMessage(r)),Promise.reject(r)}},e=>(Logger.error("Request error:",getErrorMessage(e)),Promise.reject(e))),userClient.interceptors.response.use(async e=>{const r=e.config;if(r._endReplacement)try{await storeReplacementSession(e.data)}finally{endReplacement(r)}return e},async e=>{if(endReplacement(e?.config),axios.isCancel(e))return Promise.reject(e);if(e instanceof RequestOfflineError||e instanceof NoAccessTokenError)return Promise.reject(e);if(!axios.isAxiosError(e))return Logger.error(`Non-axios error in response interceptor: ${getErrorMessage(e)}`),Promise.reject(e);const r=e,t=r.config;if(!r.response)return t?.skipErrorLog||Logger.info(`Network error or no response from server: ${r.message}, URL: ${t?.url}`),Promise.reject(e);if(isWorkspaceChangedResponse(r))return Logger.info(`Refused for another workspace. URL: ${t?.url}`),Promise.reject(new WorkspaceChangedError("Refused for another workspace",{response:r.response,config:t,cause:e}));if(401===r.response.status&&t&&!t._replayedWithCurrentToken&&!t.replacesSession&&!isRefreshTokenRequest(t.url)&&(await waitForSessionReplacement(),await currentTokenIfReplaced(readSentToken(t)))){const r=await readAccountId(getAccountIdProvider());return(t._accountId??null)!==r?(Logger.info(`Workspace changed in flight; not sent again. URL: ${t.url}`),Promise.reject(new WorkspaceChangedError("Workspace changed in flight",{config:t,cause:e}))):(Logger.info(`Session changed while the request was in flight; sending it again. URL: ${t.url}`),t._replayedWithCurrentToken=!0,userClient(t))}if(401===r.response.status&&t&&!t._retry){if(isRefreshTokenRequest(t.url))return Promise.reject(e);const s=readSignOutReason(r.response.headers),o=getSessionTerminationCode(r.response.data)??(hasSessionInvalidHeader(r.response.headers)||null!==s?SESSION_TERMINATION_CODES.TERMINATED:void 0);if(o)return Logger.warn(`Session ${o}, logging out without refresh. URL: ${t.url}`),resetRefreshState(),await endSessionAndLogout("terminated",s),Promise.reject(e);if(Logger.warn(`Unauthorized URL: ${t.url}`),t._retry=!0,isRefreshInFlight())return queueBehindRefresh().then(e=>(Logger.info("Retrying request after token refresh:",t.url),setAuthHeader(t,e),userClient(t))).catch(e=>(Logger.error("Failed to retry request after token refresh:",getErrorMessage(e)),Promise.reject(e)));try{const e=await refreshAccessToken();return setAuthHeader(t,e),userClient(t)}catch(e){return Promise.reject(e)}}return t?.skipErrorLog||Logger.error(`Response error: ${responseBodyText(r.response?.data,r.message)}, URL: ${t?.url}, Status: ${r.response.status}`),Promise.reject(e)});export default userClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{configuredLocale,getFormatterConfig,isFormatterConfigured}from"./formatConfig.js";import{numberFormat}from"./intlCache.js";const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,indianGroupingFallback=(r,t)=>{const
|
|
1
|
+
"use strict";import{configuredLocale,getFormatterConfig,isFormatterConfigured,numberSeparators,styledNumber}from"./formatConfig.js";import{numberFormat}from"./intlCache.js";const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,indianGroupingFallback=(r,t)=>{const{decimal:e,group:n}=numberSeparators()??{decimal:".",group:","},i=r<0?"-":"",o=Math.abs(r).toFixed(t),[m,u]=o.split("."),c=m.length>3?m.slice(-3):m,a=m.length>3?m.slice(0,-3):"";return i+(a?a.replace(/\B(?=(\d{2})+(?!\d))/g,n)+n+c:c)+(u?`${e}${u}`:"")},toAmount=r=>{if(null==r||"string"==typeof r&&""===r.trim())return null;const t="number"==typeof r?r:Number(r);return Number.isFinite(t)?t:null},currencyDigits=(r,t)=>numberFormat(r,{style:"currency",currency:t}).resolvedOptions().maximumFractionDigits??2;export const formatCurrency=(r,t={})=>{const{currency:e="INR",locale:n=configuredLocale()??"en-IN",minimumFractionDigits:i,maximumFractionDigits:o,stripSymbol:m=!1,empty:u=(isFormatterConfigured("locale")||isFormatterConfigured("empty")?getFormatterConfig().empty:""),...c}=t,a=toAmount(r);if(null===a)return u;if(hasIntlNumber())try{const r=o??currencyDigits(n,e),t=i??(Number.isInteger(a)?0:r),u=styledNumber(numberFormat(n,{...c,style:"currency",currency:e,minimumFractionDigits:t,maximumFractionDigits:Math.max(t,r)}),a);return m?u.replace(/[^\d,.\s\-+]/g,"").trim():u}catch{}const s=indianGroupingFallback(a,i??(Number.isInteger(a)?0:2));return m?s:"INR"===e?`₹${s}`:`${e} ${s}`};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const DEFAULTS={zone:"IST",locale:"en-IN",empty:"-"};let current={...DEFAULTS},configured=new Set;export const configureFormatters=e=>{if(void 0===e)return current={...DEFAULTS},void(configured=new Set);for(const
|
|
1
|
+
"use strict";const DEFAULTS={zone:"IST",locale:"en-IN",empty:"-"},SEPARATORS={PointWithCommaGroups:{decimal:".",group:","},CommaWithPointGroups:{decimal:",",group:"."},CommaWithSpaceGroups:{decimal:",",group:" "},PointWithSpaceGroups:{decimal:".",group:" "}},DATE_ORDERS=["DayMonthNameYear","DayMonthYear","MonthDayYear","YearMonthDay"];let current={...DEFAULTS},configured=new Set;export const configureFormatters=e=>{if(void 0===e)return current={...DEFAULTS},void(configured=new Set);if(void 0!==e.numberStyle&&!Object.hasOwn(SEPARATORS,e.numberStyle))throw new RangeError(`Unknown number style "${e.numberStyle}"; expected one of ${Object.keys(SEPARATORS).join(", ")}.`);if(void 0!==e.dateOrder&&!DATE_ORDERS.includes(e.dateOrder))throw new RangeError(`Unknown date order "${e.dateOrder}"; expected one of ${DATE_ORDERS.join(", ")}.`);for(const r of Object.keys(e)){const o=e[r];void 0!==o&&(current={...current,[r]:o},configured.add(r))}};export const getFormatterConfig=()=>({...current});export const isFormatterConfigured=e=>configured.has(e);export const configuredLocale=()=>configured.has("locale")?current.locale:null;export const groupingForLocale=e=>/-IN(?:-|$)/i.test(e)?"indian":"international";export const numberSeparators=()=>void 0===current.numberStyle?null:SEPARATORS[current.numberStyle];export const styledNumber=(e,r)=>{const o=numberSeparators();return null===o?e.format(r):e.formatToParts(r).map(e=>"decimal"===e.type?o.decimal:"group"===e.type?o.group:e.value).join("")};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{configuredLocale,getFormatterConfig,groupingForLocale}from"./formatConfig.js";import{dateTimeFormat,numberFormat,relativeTimeFormat}from"./intlCache.js";const MONTHS=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],IST_OFFSET_MINUTES=330,IST_NAMES=["IST","Asia/Kolkata","Asia/Calcutta"],DATE_ONLY=/^\d{4}-\d{2}-\d{2}$/,pad2=t=>t<10?`0${t}`:`${t}`,emptyOf=t=>t??getFormatterConfig().empty,toInstant=t=>{if(null==t||""===t)return null;const e=t instanceof Date?t:new Date("string"==typeof t?t.trim():t);return Number.isNaN(e.getTime())?null:e},isDateOnly=t=>"string"==typeof t&&DATE_ONLY.test(t.trim()),gmtLabel=t=>{if(0===t)return"GMT";const e=t>0?"+":"-",n=Math.abs(t),
|
|
1
|
+
"use strict";import{configuredLocale,getFormatterConfig,groupingForLocale,numberSeparators,styledNumber}from"./formatConfig.js";import{dateTimeFormat,numberFormat,relativeTimeFormat}from"./intlCache.js";const MONTHS=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],IST_OFFSET_MINUTES=330,IST_NAMES=["IST","Asia/Kolkata","Asia/Calcutta"],DATE_ONLY=/^\d{4}-\d{2}-\d{2}$/,pad2=t=>t<10?`0${t}`:`${t}`,emptyOf=t=>t??getFormatterConfig().empty,toInstant=t=>{if(null==t||""===t)return null;const e=t instanceof Date?t:new Date("string"==typeof t?t.trim():t);return Number.isNaN(e.getTime())?null:e},isDateOnly=t=>"string"==typeof t&&DATE_ONLY.test(t.trim()),gmtLabel=t=>{if(0===t)return"GMT";const e=t>0?"+":"-",n=Math.abs(t),r=n%60;return`GMT${e}${Math.floor(n/60)}${0===r?"":`:${pad2(r)}`}`},shifted=(t,e,n)=>{const r=new Date(t.getTime()+6e4*e);return{year:r.getUTCFullYear(),month:r.getUTCMonth(),day:r.getUTCDate(),hour:r.getUTCHours(),minute:r.getUTCMinutes(),label:n}},inIanaZone=(t,e)=>{const n=dateTimeFormat("en-US",{timeZone:e,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",hour12:!1}).formatToParts(t),read=t=>Number.parseInt(n.find(e=>e.type===t)?.value??"",10),r=read("year"),o=read("month")-1,i=read("day"),a=read("hour")%24,m=read("minute"),l=Date.UTC(r,o,i,a,m),u=Math.round((l-6e4*Math.floor(t.getTime()/6e4))/6e4);return{year:r,month:o,day:i,hour:a,minute:m,label:gmtLabel(u)}},wallClock=(t,e)=>IST_NAMES.includes(e)?shifted(t,330,"IST"):"UTC"===e?shifted(t,0,"UTC"):"viewer"===e?{year:t.getFullYear(),month:t.getMonth(),day:t.getDate(),hour:t.getHours(),minute:t.getMinutes(),label:gmtLabel(-t.getTimezoneOffset())}:inIanaZone(t,e),hourCycleOf=t=>t.hourCycle??12,dayMonthYear=t=>`${pad2(t.day)}-${MONTHS[t.month]}-${t.year}`,numericDate=(t,e)=>{const n=pad2(t.day),r=pad2(t.month+1),o=String(t.year).padStart(4,"0");return"DayMonthYear"===e?`${n}/${r}/${o}`:"MonthDayYear"===e?`${r}/${n}/${o}`:`${o}-${r}-${n}`},clockTime=(t,e)=>24===e?`${pad2(t.hour)}:${pad2(t.minute)}`:`${t.hour%12||12}:${pad2(t.minute)} ${t.hour<12?"AM":"PM"}`,labelled=(t,e)=>e??!IST_NAMES.includes(t),withLabel=(t,e,n,r)=>labelled(n,r)?`${t} ${e.label}`:t,intlZone=t=>{if("viewer"!==t)return IST_NAMES.includes(t)?"Asia/Kolkata":t},localeDayMonthYear=(t,e,n)=>{const r=dateTimeFormat(e,{day:"2-digit",month:"short",year:"numeric",timeZone:n}).formatToParts(t),part=t=>r.find(e=>e.type===t)?.value??"";return`${part("day")}-${part("month").replace(".","")}-${part("year")}`},dateText=(t,e)=>{const n=getFormatterConfig().dateOrder??"DayMonthNameYear";if("DayMonthNameYear"!==n)return numericDate(wallClock(t,e),n);const r=configuredLocale();return r?localeDayMonthYear(t,r,intlZone(e)):dayMonthYear(wallClock(t,e))},localeClock=(t,e,n,r)=>dateTimeFormat(e,{hour:"2-digit",minute:"2-digit",timeZone:intlZone(n),timeZoneName:labelled(n,r.zoneLabel)?"short":void 0,hourCycle:void 0===r.hourCycle?void 0:24===r.hourCycle?"h23":"h12"}).format(t);export const formatDate=(t,e={})=>{const n=toInstant(t);return n?dateText(n,isDateOnly(t)?"UTC":e.zone??getFormatterConfig().zone):emptyOf(e.empty)};export const formatTime=(t,e={})=>{const n=toInstant(t);if(!n)return emptyOf(e.empty);const r=e.zone??getFormatterConfig().zone,o=configuredLocale();if(o)return localeClock(n,o,r,e);const i=wallClock(n,r);return withLabel(clockTime(i,hourCycleOf(e)),i,r,e.zoneLabel)};export const formatDateTime=(t,e={})=>{const n=toInstant(t);if(!n)return emptyOf(e.empty);const r=e.zone??getFormatterConfig().zone,o=configuredLocale();if(o)return`${dateText(n,r)}, ${localeClock(n,o,r,e)}`;const i=wallClock(n,r);return withLabel(`${dateText(n,r)}, ${clockTime(i,hourCycleOf(e))}`,i,r,e.zoneLabel)};const SECOND=1e3,MINUTE=6e4,HOUR=36e5,DAY=24*HOUR,WEEK=7*DAY,MONTH=30*DAY,YEAR=365*DAY,INTL_UNITS=[["year",YEAR],["month",MONTH],["day",DAY],["hour",HOUR],["minute",6e4]];export const formatRelative=(t,e={})=>{const n=toInstant(t),r=toInstant(e.now??Date.now());if(!n||!r)return emptyOf(e.empty);const o=n.getTime()-r.getTime(),i=Math.abs(o),a=Intl.RelativeTimeFormat,m=configuredLocale();if((null!==m||!0===e.intl)&&"function"==typeof a){const t=relativeTimeFormat(a,m??getFormatterConfig().locale),[e,n]=INTL_UNITS.find(([,t])=>i>=t)??["second",1e3];return t.format(Math.round(o/n),e)}if(i<6e4)return"just now";const[l,u]=i<HOUR?["minute",6e4]:i<DAY?["hour",HOUR]:i<WEEK?["day",DAY]:i<MONTH?["week",WEEK]:i<YEAR?["month",MONTH]:["year",YEAR],c=Math.floor(i/u),s=`${c} ${l}${1===c?"":"s"}`;return o<0?`${s} ago`:`in ${s}`};const toNumber=t=>{if(null==t)return null;if("string"==typeof t&&""===t.trim())return null;const e="number"==typeof t?t:Number(t);return Number.isFinite(e)?e:null},clampDigits=t=>Math.min(20,Math.max(0,Math.trunc(t))),shiftDecimal=(t,e)=>/e/i.test(String(t))?t*10**e:Number(`${t}e${e}`),houseSeparators=()=>numberSeparators()??{decimal:".",group:","},groupInteger=(t,e,n)=>{if("none"===e||t.length<=3)return t;if("international"===e)return t.replace(/\B(?=(\d{3})+(?!\d))/g,n);return`${t.slice(0,-3).replace(/\B(?=(\d{2})+(?!\d))/g,n)}${n}${t.slice(-3)}`},hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,plainDigits=(t,e)=>{if(hasIntlNumber())return numberFormat("en-US",{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:e}).format(t);const n=Math.min(e,15);return shiftDecimal(Math.round(shiftDecimal(t,n)),-n).toFixed(n)},decimalText=(t,e,n,r)=>{const o=Math.max(clampDigits(n),clampDigits(e)),i=clampDigits(e),a=plainDigits(Math.abs(t),o),[m="0",l=""]=a.split(".");let u=l.padEnd(i,"0");for(;u.length>i&&u.endsWith("0");)u=u.slice(0,-1);const c=houseSeparators(),s=groupInteger(m,r,c.group)+(u?`${c.decimal}${u}`:"");return t<0&&/[1-9]/.test(a)?`-${s}`:s},HOUSE_NUMBER_KEYS=new Set(["grouping","minimumFractionDigits","maximumFractionDigits","locale","empty","scale"]),intlNumberOptions=t=>{if(!Object.entries(t).some(([t,e])=>void 0!==e&&!HOUSE_NUMBER_KEYS.has(t)))return null;const{grouping:e,locale:n,empty:r,scale:o,...i}=t;return"none"===e&&void 0===i.useGrouping?{...i,useGrouping:!1}:i},localeOf=t=>t.locale??getFormatterConfig().locale,intlTextLocale=t=>{const e=configuredLocale();return null===e||"indian"===t.grouping||"international"===t.grouping?null:t.locale??e},fractionDigits=(t,e)=>{const n=clampDigits(t);return{minimumFractionDigits:n,maximumFractionDigits:Math.max(n,clampDigits(e))}},groupingOption=t=>"none"===t?{useGrouping:!1}:{};export const formatNumber=(t,e={})=>{const n=toNumber(t);if(null===n)return emptyOf(e.empty);const r=intlNumberOptions(e);if(r)return styledNumber(numberFormat(localeOf(e),r),n);const o=intlTextLocale(e);return o?styledNumber(numberFormat(o,{...fractionDigits(e.minimumFractionDigits??0,e.maximumFractionDigits??3),...groupingOption(e.grouping)}),n):decimalText(n,e.minimumFractionDigits??0,e.maximumFractionDigits??3,e.grouping??groupingForLocale(localeOf(e)))};export const formatPercent=(t,e={})=>{const n=toNumber(t);if(null===n)return emptyOf(e.empty);const r=intlNumberOptions(e);if(r){const t="percent"===e.scale?shiftDecimal(n,-2):n;return styledNumber(numberFormat(localeOf(e),{style:"percent",...r}),t)}const o=intlTextLocale(e);if(o){const t="percent"===e.scale?shiftDecimal(n,-2):n;return styledNumber(numberFormat(o,{style:"percent",...fractionDigits(e.minimumFractionDigits??0,e.maximumFractionDigits??e.minimumFractionDigits??0),...groupingOption(e.grouping)}),t)}const i="percent"===e.scale?n:shiftDecimal(n,2);return`${decimalText(i,e.minimumFractionDigits??0,e.maximumFractionDigits??e.minimumFractionDigits??0,e.grouping??groupingForLocale(localeOf(e)))}%`};const SYMBOLS={INR:"₹",USD:"$",EUR:"€",GBP:"£"},MINOR_DIGITS={JPY:0,KRW:0,VND:0,BHD:3,JOD:3,KWD:3,OMR:3,TND:3};export const formatMinor=(t,e={})=>{const n=toNumber(t);if(null===n)return emptyOf(e.empty);const r=(e.currency??"INR").toUpperCase(),o=MINOR_DIGITS[r]??2,i=Math.round(Math.abs(n)),a=String(i).padStart(o+1,"0"),m=a.slice(0,a.length-o);let l=a.slice(a.length-o);e.dropZeroDecimals&&/^0*$/.test(l)&&(l="");const u=intlTextLocale({grouping:e.grouping});if(u)try{const t=Number(`${n<0&&0!==i?"-":""}${m}.${a.slice(a.length-o)||"0"}`);return styledNumber(numberFormat(u,{...!1===e.symbol?{}:{style:"currency",currency:r},...fractionDigits(l?o:0,o),...groupingOption(e.grouping)}),t)}catch{}const c=e.grouping??("INR"===r?"indian":"international"),s=houseSeparators(),g=groupInteger(m,c,s.group)+(l?`${s.decimal}${l}`:""),p=n<0&&0!==i?"-":"";if(!1===e.symbol)return`${p}${g}`;const f=SYMBOLS[r];return f?`${p}${f}${g}`:`${p}${r} ${g}`};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{formatNumber as houseNumber,formatPercent as housePercent}from"./house.js";import{numberFormat}from"./intlCache.js";const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat;export function formatNumber(t,r,e){if("number"!=typeof r&&void 0===e)return houseNumber(t,r);const n="number"==typeof r?r:void 0,
|
|
1
|
+
"use strict";import{numberSeparators,styledNumber}from"./formatConfig.js";import{formatNumber as houseNumber,formatPercent as housePercent}from"./house.js";import{numberFormat}from"./intlCache.js";const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,withDecimalMark=t=>{const r=numberSeparators();return null===r?t:t.replace(".",r.decimal)};export function formatNumber(t,r,e){if("number"!=typeof r&&void 0===e)return houseNumber(t,r);const n="number"==typeof r?r:void 0,i=t;if(null==i||Number.isNaN(i))return"";if(hasIntlNumber())try{const t={};return null!=n&&(t.minimumFractionDigits=n,t.maximumFractionDigits=n),styledNumber(numberFormat(e??"en-IN",t),i)}catch{}return withDecimalMark(null!=n?i.toFixed(n):String(i))}export function formatPercent(t,r,e,n){if("number"!=typeof r&&void 0===e&&void 0===n)return housePercent(t,r);const i="number"==typeof r?r:0,m=t;if(null==m||Number.isNaN(m))return"";const o=e??1?m:m/100;if(hasIntlNumber())try{return styledNumber(numberFormat(n??"en-IN",{style:"percent",minimumFractionDigits:i,maximumFractionDigits:i}),o)}catch{}return`${withDecimalMark((100*o).toFixed(i))}%`}export const formatCompactNumber=(t,r="en-IN")=>{if(null==t||Number.isNaN(t))return"";if(hasIntlNumber())try{return styledNumber(numberFormat(r,{notation:"compact",maximumFractionDigits:1}),t)}catch{}const e=Math.abs(t),n=t<0?"-":"";return e>=1e7?`${n}${withDecimalMark((e/1e7).toFixed(1))}Cr`:e>=1e5?`${n}${withDecimalMark((e/1e5).toFixed(1))}L`:e>=1e3?`${n}${withDecimalMark((e/1e3).toFixed(1))}K`:withDecimalMark(`${t}`)};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{getConfigValue}from"../config/index.js";import{isNoResponse}from"../errors/extractApiError.js";import{redact,redactString}from"./redact.js";const Colors={RESET:"[0m",GRAY:"[90m",BLUE:"[34m",YELLOW:"[33m",RED_BOLD:"[31;1m"},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{}},toErrorObject=e=>{if(e instanceof Error)return e;if("string"==typeof e)return new Error(e);try{return new Error(JSON.stringify(e))}catch{return new Error(String(e))}};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};let loggerOptions={...DEFAULT_LOGGER_OPTIONS};export const configureLogger=e=>{loggerOptions={...loggerOptions,...e},screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit))};let currentScreen=null,screenHistory=[];const 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:
|
|
1
|
+
"use strict";import{getConfigValue}from"../config/index.js";import{isNoResponse}from"../errors/extractApiError.js";import{redact,redactString}from"./redact.js";const Colors={RESET:"[0m",GRAY:"[90m",BLUE:"[34m",YELLOW:"[33m",RED_BOLD:"[31;1m"},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{}},toErrorObject=e=>{if(e instanceof Error)return e;if("string"==typeof e)return new Error(e);try{return new Error(JSON.stringify(e))}catch{return new Error(String(e))}};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};let loggerOptions={...DEFAULT_LOGGER_OPTIONS};export const configureLogger=e=>{loggerOptions={...loggerOptions,...e},screenHistory.length>loggerOptions.screenHistoryLimit&&(screenHistory=screenHistory.slice(screenHistory.length-loggerOptions.screenHistoryLimit))};let currentScreen=null,screenHistory=[];const 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:n}=shouldForward(o);t&&safe(()=>remote?.recordError?.(e,buildErrorContext(r,n)))},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 n=t[0];void 0===n||isNoResponse(r[0])||forwardErrorToRemote(toErrorObject(n),{source:"Logger.error",message:o})},breadcrumb=(e,r)=>{const o=redactString(e),t=redact(r);isEnabled()&&isLogLevelAllowed("info")&&console.info(`${Colors.BLUE}[BREADCRUMB]: ${o}${Colors.RESET}`,t??""),safe(()=>remote?.breadcrumb?.(o,t))},recordError=(e,r)=>{const o=redact(toErrorObject(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=[],...n}=r,s=asDict(e),l=asDict(s?.config),i=asDict(s?.response),c=asDict(i?.data),d="number"==typeof i?.status?i.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"===s?.name||"ERR_CANCELED"===s?.code||!0===s?.__CANCEL__)return void logInfo(`${u} canceled`);if("RequestOfflineError"===s?.name)return void logInfo(`${u} not sent (offline)`);if(isNoResponse(e))return void logInfo(`${u} got no response`);if("WorkspaceChangedError"===s?.name||"workspace_changed"===c?.code)return void logInfo(`${u} refused (another workspace)`);if(null!==d&&t.includes(d))return void logInfo(`${u} refused (${d})`);const f="string"==typeof s?.message?s.message:e instanceof Error?e.message:null,p=redactString(null===d?`${u} failed`:`${u} failed (${d})`);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${p}${Colors.RESET}`,redactString(f??"")),safe(()=>remote?.log?.("error",p,[]));const E=getConfigValue("correlationIdHeader",null),L=redact({source:"Logger.requestFailed",label:u,status:d,method:a,path:g,code:"string"==typeof c?.code?c.code:null,traceId:"string"==typeof c?.traceId?c.traceId:null,correlationId:E?headerValue(l?.headers,E):null,detail:f,...n});forwardErrorToRemote(redact(new Error(p)),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];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};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{Linking}from"react-native";import{Logger}from"../logger/index.js";let backend=null;export const setPermissionsImplementation=e=>{backend=e};const registry=new Map;export const registerPermissionAdapter=(e,t)=>{registry.set(e,t)};const resolveExpoModule=e=>registry.get(e)??null,toStatus=e=>e?"limited"===e.accessPrivileges?"limited":"granted"===e.status?"granted":"denied"===e.status?e.canAskAgain?"denied":"blocked":"
|
|
1
|
+
"use strict";import{Linking}from"react-native";import{Logger}from"../logger/index.js";let backend=null;export const setPermissionsImplementation=e=>{backend=e};const registry=new Map;export const registerPermissionAdapter=(e,t)=>{registry.set(e,t)};const resolveExpoModule=e=>registry.get(e)??null,toStatus=e=>e?"limited"===e.accessPrivileges?"limited":"granted"===e.status?"granted":"denied"===e.status?e.canAskAgain?"denied":"blocked":"undetermined":"unavailable",checkPermission=async e=>{if(backend)return backend.check(e);const t=resolveExpoModule(e);if(!t)return"unavailable";try{return toStatus(await t.check())}catch(t){return Logger.error(`[permissions] check(${e}) failed`,t),"unavailable"}},requestPermission=async e=>{if(backend)return backend.request(e);const t=resolveExpoModule(e);if(!t)return"unavailable";try{return toStatus(await t.request())}catch(t){return Logger.error(`[permissions] request(${e}) failed`,t),"unavailable"}},openAppSettings=async()=>{try{return await Linking.openSettings(),!0}catch(e){return Logger.error("[permissions] openAppSettings failed",e),!1}};export const Permissions={check:checkPermission,request:requestPermission,isAuthorized:async e=>{const t=await checkPermission(e);return"granted"===t||"limited"===t},ensure:async e=>{const t=await checkPermission(e);return"undetermined"===t||"denied"===t?requestPermission(e):t},openSettings:openAppSettings};
|
package/lib/module/push/push.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useSyncExternalStore}from"react";import{Platform}from"react-native";import{Logger}from"../logger/index.js";let resolved,override=null;export const setPushImplementation=e=>{override=e};export const resolveModules=()=>{if(override)return override;if(void 0!==resolved)return resolved;try{if(require("expo").isRunningInExpoGo())return resolved=null,resolved;const e=require("expo-notifications"),t=require("expo-application");resolved={notifications:e,applicationId:t.applicationId,getApnsEnvironment:()=>t.getIosPushNotificationServiceEnvironmentAsync()}}catch(e){Logger.warn("[push] expo-notifications is not available; push is off",e),resolved=null}return resolved};let state={status:"unknown",enabled:!1};const subscribers=new Set,setState=e=>{state={...state,...e};for(const e of subscribers)e()};let config=null,channelsReady=Promise.resolve(),tokenSubscription=null,actionHandler=null;const receiveHandlers=new Set;let listening=!1,listeningForReceived=!1;const pendingResponses=[],routedAt=new Map,REPEAT_WINDOW_MS=1e4,requireConfig=()=>{if(!config)throw new Error("[@webority/mobile-core] call initPush before enablePush or disablePush.");return config},toPermissionStatus=e=>e.granted?"granted":"denied"===e.status?"denied":"
|
|
1
|
+
"use strict";import{useSyncExternalStore}from"react";import{Platform}from"react-native";import{Logger}from"../logger/index.js";let resolved,override=null;export const setPushImplementation=e=>{override=e};export const resolveModules=()=>{if(override)return override;if(void 0!==resolved)return resolved;try{if(require("expo").isRunningInExpoGo())return resolved=null,resolved;const e=require("expo-notifications"),t=require("expo-application");resolved={notifications:e,applicationId:t.applicationId,getApnsEnvironment:()=>t.getIosPushNotificationServiceEnvironmentAsync()}}catch(e){Logger.warn("[push] expo-notifications is not available; push is off",e),resolved=null}return resolved};let state={status:"unknown",enabled:!1};const subscribers=new Set,setState=e=>{state={...state,...e};for(const e of subscribers)e()};let config=null,channelsReady=Promise.resolve(),tokenSubscription=null,actionHandler=null;const receiveHandlers=new Set;let listening=!1,listeningForReceived=!1;const pendingResponses=[],routedAt=new Map,REPEAT_WINDOW_MS=1e4,requireConfig=()=>{if(!config)throw new Error("[@webority/mobile-core] call initPush before enablePush or disablePush.");return config},toPermissionStatus=e=>e.granted?"granted":"denied"===e.status?e.canAskAgain?"denied":"blocked":"undetermined",toStringData=e=>{const t={};for(const[n,o]of Object.entries(e??{}))null!=o&&(t[n]="object"==typeof o?JSON.stringify(o):String(o));return t},contentData=e=>{const t=e.request.content;if(t.data)return toStringData(t.data);if("string"==typeof t.dataString)try{return toStringData(JSON.parse(t.dataString))}catch(e){Logger.error("[push] notification data is not JSON",e)}return{}},triggerData=e=>{const t=e.request.trigger,n={...t?.remoteMessage?.data??{}};for(const[e,o]of Object.entries(t?.payload??{}))"aps"===e||"body"===e&&"object"==typeof o||(n[e]=o);return toStringData(n)},notificationData=e=>({...triggerData(e),...contentData(e)}),responseData=e=>notificationData(e.notification);export const toPushReceived=e=>({notificationId:e.request.identifier,title:e.request.content.title??null,body:e.request.content.body??null,data:notificationData(e)});export const toPushAction=e=>({actionId:e.actionIdentifier,...e.userText?{userText:e.userText}:{},data:responseData(e),notificationId:e.notification.request.identifier});export const toNotificationActions=e=>e.map(e=>({identifier:e.id,buttonTitle:e.title,...e.textInput?{textInput:{submitButtonTitle:e.textInput.submitTitle,placeholder:e.textInput.placeholder}}:{},options:{opensAppToForeground:e.opensApp??!0,isDestructive:e.destructive??!1,isAuthenticationRequired:e.authenticationRequired??!1}}));const routeResponse=async(e,t)=>{const n=`${t.notification.request.identifier}:${t.actionIdentifier}`,o=routedAt.get(n);if(void 0!==o&&Date.now()-o<1e4)return;if(t.actionIdentifier!==e.DEFAULT_ACTION_IDENTIFIER&&actionHandler){routedAt.set(n,Date.now());try{await actionHandler(toPushAction(t))}catch(e){Logger.error("[push] onAction threw",e)}}else if(config){routedAt.set(n,Date.now());try{config.onOpen(responseData(t))}catch(e){Logger.error("[push] onOpen threw",e)}}else pendingResponses.push(t)},drainPending=async e=>{const t=pendingResponses.splice(0);for(const n of t)await routeResponse(e,n)},listenForResponses=e=>{listening||(listening=!0,e.addNotificationResponseReceivedListener(t=>{routeResponse(e,t)}),e.getLastNotificationResponseAsync().then(async t=>(t&&await routeResponse(e,t),e.clearLastNotificationResponseAsync?.())).catch(e=>Logger.error("[push] reading the launch notification failed",e)))};export const routeTaskPayload=async e=>{const t=resolveModules(),n=e;t&&"string"==typeof n?.actionIdentifier&&"string"==typeof n.notification?.request?.identifier&&await routeResponse(t.notifications,n)};const createChannels=async(e,t)=>{for(const n of t)try{await e.setNotificationChannelAsync(n.id,{name:n.name,importance:"high"===n.importance?e.AndroidImportance.HIGH:e.AndroidImportance.DEFAULT})}catch(e){Logger.error(`[push] creating channel ${n.id} failed`,e)}},APNS_ENVIRONMENTS={development:"Development",production:"Production"},readApnsEnvironment=async e=>{try{return APNS_ENVIRONMENTS[await e.getApnsEnvironment()??""]??null}catch(e){return Logger.warn("[push] reading the APNs environment failed",e),null}},toDevice=async(e,t)=>{const n="android"===e.type?"Fcm":"ios"===e.type?"Apns":null;if(!n||"string"!=typeof e.data)return null;if(!t.applicationId)throw new Error("[@webority/mobile-core] push needs the app bundle id from expo-application.");return{installationId:await requireConfig().getInstallationId(),platform:n,token:e.data,appId:t.applicationId,apnsEnvironment:"Apns"===n?await readApnsEnvironment(t):null}};export const initPush=e=>{const t=null===config;if(config=e,!t)return;const n=resolveModules();if(!n)return void setState({status:"unavailable"});const o=n.notifications;o.setNotificationHandler({handleNotification:async()=>{const e=config?.showInForeground?.()??!0;return{shouldShowBanner:e,shouldShowList:e,shouldPlaySound:e&&(config?.playSoundInForeground?.()??!0),shouldSetBadge:!0}}}),"android"===Platform.OS&&e.androidChannels?.length&&(channelsReady=createChannels(o,e.androidChannels)),listenForResponses(o),drainPending(o),o.getPermissionsAsync().then(e=>setState({status:toPermissionStatus(e)})).catch(e=>Logger.error("[push] permission check failed",e))};let registering=null,registeredKey=null,unregistering=null,tokenDrop=Promise.resolve();const registerOnce=e=>{const t=JSON.stringify(e);if(registering?.key===t)return registering.promise;const n=requireConfig().register(e).then(()=>{registeredKey=t}).finally(()=>{registering?.promise===n&&(registering=null)});return registering={key:t,promise:n},n};export const enablePush=async({prompt:e=!0}={})=>{requireConfig();const t=resolveModules();if(!t)return setState({status:"unavailable"}),"unavailable";const n=t.notifications;await channelsReady,await tokenDrop;let o=await n.getPermissionsAsync();if(!o.granted&&e&&(o=await n.requestPermissionsAsync()),!o.granted){const e=toPermissionStatus(o);return setState({status:e}),e}const i=await toDevice(await n.getDevicePushTokenAsync(),t);return i?(await registerOnce(i),tokenSubscription?.remove(),tokenSubscription=n.addPushTokenListener(e=>{(unregistering??Promise.resolve()).then(()=>state.enabled?toDevice(e,t):null).then(e=>e&&JSON.stringify(e)!==registeredKey?registerOnce(e):void 0).catch(e=>Logger.error("[push] re-registering a new token failed",e))}),setState({status:"granted",enabled:!0}),"granted"):(setState({status:"unavailable"}),"unavailable")};const stopFollowingToken=()=>{tokenSubscription?.remove(),tokenSubscription=null,registeredKey=null,setState({enabled:!1})};export const disablePush=async()=>{const e=requireConfig(),t=await e.getInstallationId();await(registering?.promise.catch(()=>{}));let settle=()=>{};const n=new Promise(e=>{settle=e});unregistering=n;try{await e.unregister(t),stopFollowingToken()}finally{unregistering===n&&(unregistering=null),settle()}};export const resetPush=async()=>{stopFollowingToken();const e=resolveModules();if(!e)return;const t=e.notifications.unregisterForNotificationsAsync();tokenDrop=t.catch(()=>{}),await t};export const setBadgeCount=async e=>{const t=resolveModules();t&&await t.notifications.setBadgeCountAsync(e)};export const setCategories=async e=>{const t=resolveModules();if(t)for(const n of e)await t.notifications.setNotificationCategoryAsync(n.id,toNotificationActions(n.actions))};export const onAction=e=>{actionHandler=e;const t=resolveModules();return t&&(listenForResponses(t.notifications),drainPending(t.notifications)),()=>{actionHandler===e&&(actionHandler=null)}};export const onReceive=e=>{receiveHandlers.add(e);const t=resolveModules();return t&&!listeningForReceived&&(listeningForReceived=!0,t.notifications.addNotificationReceivedListener(e=>{const t=toPushReceived(e);for(const e of[...receiveHandlers])try{e(t)}catch(e){Logger.error("[push] onReceive threw",e)}})),()=>{receiveHandlers.delete(e)}};export const notifyLocal=async({title:e,body:t,data:n})=>{const o=resolveModules();o&&await o.notifications.scheduleNotificationAsync({content:{title:e,body:t,data:n??{}},trigger:null})};const subscribe=e=>(subscribers.add(e),()=>{subscribers.delete(e)}),getSnapshot=()=>state,enable=async()=>{await enablePush()};export const usePush=()=>({...useSyncExternalStore(subscribe,getSnapshot,getSnapshot),enable:enable,disable:disablePush});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const PUSH_STATUS={unknown:"unknown",granted:"granted",denied:"denied",unavailable:"unavailable"};
|
|
1
|
+
"use strict";export const PUSH_STATUS={unknown:"unknown",undetermined:"undetermined",granted:"granted",denied:"denied",blocked:"blocked",unavailable:"unavailable"};
|
|
@@ -25,6 +25,8 @@ export interface FormatCurrencyOptions extends Omit<Intl.NumberFormatOptions, 's
|
|
|
25
25
|
* options: "₹1,50,000" for 150000, "₹1,234.50" for 1234.5, and `''` for a missing amount.
|
|
26
26
|
* Once the app configures a locale (`configureFormatters({ locale })`), the amount is
|
|
27
27
|
* written in that locale and a missing amount prints the configured placeholder ("-").
|
|
28
|
+
* A configured `numberStyle` sets the decimal mark and group separator; the locale keeps
|
|
29
|
+
* its group sizes and symbol placement ("₹1.50.000,50" for `'CommaWithPointGroups'`).
|
|
28
30
|
* A numeric string reads as its number. For money the API carries in minor units (paise),
|
|
29
31
|
* use `formatMinor`.
|
|
30
32
|
*
|
|
@@ -12,12 +12,35 @@
|
|
|
12
12
|
* "8:05 PM", "1,23,456.79"). Configuring a locale hands the words and
|
|
13
13
|
* separators to Intl for that locale: month names, digit separators, the
|
|
14
14
|
* 12- or 24-hour clock and its AM/PM casing, zone names and relative phrases.
|
|
15
|
-
* The date order stays DD-MMM-YYYY either way.
|
|
15
|
+
* The date order stays DD-MMM-YYYY either way, unless a date order is set.
|
|
16
|
+
*
|
|
17
|
+
* Personal style: a product that lets a person choose how numbers and dates
|
|
18
|
+
* read sets `numberStyle` and `dateOrder`. The number style swaps only the
|
|
19
|
+
* decimal mark and the group separator, so the locale's group sizes (en-IN's
|
|
20
|
+
* 12,34,567) and its currency symbol placement stay. The date order changes
|
|
21
|
+
* only the date; the time of day, the zone and relative phrases are untouched.
|
|
16
22
|
*/
|
|
17
23
|
/** `'IST'`: every instant in India Standard Time. `'viewer'`: the device or browser zone, labelled. */
|
|
18
24
|
export type ZoneMode = 'IST' | 'viewer';
|
|
19
25
|
/** How the integer part of a number is grouped. */
|
|
20
26
|
export type NumberGrouping = 'indian' | 'international' | 'none';
|
|
27
|
+
/**
|
|
28
|
+
* The decimal mark and group separator of every number: `'PointWithCommaGroups'` "1,234.5",
|
|
29
|
+
* `'CommaWithPointGroups'` "1.234,5", `'CommaWithSpaceGroups'` "1 234,5", `'PointWithSpaceGroups'`
|
|
30
|
+
* "1 234.5". The space is a no-break space (U+00A0), so a number never wraps.
|
|
31
|
+
*/
|
|
32
|
+
export type NumberStyle = 'PointWithCommaGroups' | 'CommaWithPointGroups' | 'CommaWithSpaceGroups' | 'PointWithSpaceGroups';
|
|
33
|
+
/**
|
|
34
|
+
* The order of every date: `'DayMonthNameYear'` "09-Oct-2026" (the house order, month name from the
|
|
35
|
+
* locale when one is configured), `'DayMonthYear'` "09/10/2026", `'MonthDayYear'` "10/09/2026",
|
|
36
|
+
* `'YearMonthDay'` "2026-10-09".
|
|
37
|
+
*/
|
|
38
|
+
export type DateOrder = 'DayMonthNameYear' | 'DayMonthYear' | 'MonthDayYear' | 'YearMonthDay';
|
|
39
|
+
/** The two characters a number style puts in a number. */
|
|
40
|
+
export interface NumberSeparators {
|
|
41
|
+
decimal: string;
|
|
42
|
+
group: string;
|
|
43
|
+
}
|
|
21
44
|
export interface FormatterConfig {
|
|
22
45
|
/** Default zone for every date and time formatter. */
|
|
23
46
|
zone: ZoneMode;
|
|
@@ -30,11 +53,17 @@ export interface FormatterConfig {
|
|
|
30
53
|
locale: string;
|
|
31
54
|
/** What every formatter returns for a missing or unreadable value. */
|
|
32
55
|
empty: string;
|
|
56
|
+
/** The person's number style. Unset, the separators are the house text's or the configured locale's. */
|
|
57
|
+
numberStyle?: NumberStyle;
|
|
58
|
+
/** The person's date order. Unset, dates read DD-MMM-YYYY. */
|
|
59
|
+
dateOrder?: DateOrder;
|
|
33
60
|
}
|
|
34
61
|
/**
|
|
35
|
-
* Set the zone mode, locale
|
|
36
|
-
*
|
|
37
|
-
* Passing nothing restores the defaults (IST,
|
|
62
|
+
* Set the zone mode, locale, empty placeholder, number style or date order for the whole app.
|
|
63
|
+
* Call it at startup, and again when the person changes their number style or date order; a key
|
|
64
|
+
* left out (or undefined) keeps its current value. Passing nothing restores the defaults (IST,
|
|
65
|
+
* en-IN, "-", house text, no number style or date order). An unknown number style or date order
|
|
66
|
+
* throws a RangeError, so a bad stored preference fails where it is applied.
|
|
38
67
|
*/
|
|
39
68
|
export declare const configureFormatters: (config?: Partial<FormatterConfig>) => void;
|
|
40
69
|
/** The settings in force, as a copy. */
|
|
@@ -45,4 +74,11 @@ export declare const isFormatterConfigured: (key: keyof FormatterConfig) => bool
|
|
|
45
74
|
export declare const configuredLocale: () => string | null;
|
|
46
75
|
/** The grouping a locale implies: Indian for a locale whose region is IN. */
|
|
47
76
|
export declare const groupingForLocale: (locale: string) => NumberGrouping;
|
|
77
|
+
/** The configured number style's separators, else null (the house text's or the locale's own). */
|
|
78
|
+
export declare const numberSeparators: () => NumberSeparators | null;
|
|
79
|
+
/**
|
|
80
|
+
* `format.format(n)`, with the configured number style's decimal mark and group separator in place
|
|
81
|
+
* of the locale's. Only those two parts change, so group sizes, signs and symbols stay the locale's.
|
|
82
|
+
*/
|
|
83
|
+
export declare const styledNumber: (format: Intl.NumberFormat, n: number) => string;
|
|
48
84
|
//# sourceMappingURL=formatConfig.d.ts.map
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
* from Intl for that locale and the date order stays DD-MMM-YYYY. For en-IN in the viewer zone:
|
|
27
27
|
* "08-Sept-2026", "08:05 pm", "08-Sept-2026, 08:05 pm IST", "yesterday", "12,34,567.891",
|
|
28
28
|
* "₹1,50,000". For de-DE: "08-Sept-2026", "20:05", "1.234.567,891".
|
|
29
|
+
*
|
|
30
|
+
* A configured `numberStyle` puts its decimal mark and group separator in every number and amount,
|
|
31
|
+
* whichever path wrote it: "1.23.456,789" for `'CommaWithPointGroups'` with the house text. A
|
|
32
|
+
* configured `dateOrder` other than DD-MMM-YYYY writes the date as digits from the wall clock,
|
|
33
|
+
* in every locale: "08/04/2026", "04/08/2026", "2026-04-08".
|
|
29
34
|
*/
|
|
30
35
|
import { type NumberGrouping, type ZoneMode } from './formatConfig';
|
|
31
36
|
/** A date the house formatters accept; null, undefined and "" read as missing. */
|
|
@@ -102,8 +107,8 @@ export interface FormatMinorOptions {
|
|
|
102
107
|
empty?: string;
|
|
103
108
|
}
|
|
104
109
|
/**
|
|
105
|
-
* "08-Apr-2026". A bare calendar date ("2026-04-08")
|
|
106
|
-
* an instant shows its day in the configured zone.
|
|
110
|
+
* "08-Apr-2026", or the configured date order. A bare calendar date ("2026-04-08")
|
|
111
|
+
* always shows as that day; an instant shows its day in the configured zone.
|
|
107
112
|
*/
|
|
108
113
|
export declare const formatDate: (value: DateValue, options?: FormatDateOptions) => string;
|
|
109
114
|
/** "8:05 PM" in IST, "8:05 PM GMT-4" in the viewer's zone; "20:05" for a configured locale with a 24-hour clock. */
|
|
@@ -3,7 +3,7 @@ export { formatCurrency } from './currency';
|
|
|
3
3
|
export type { DateInput, DateStyle, TimeStyle } from './date';
|
|
4
4
|
export { formatDate, formatDateTime, formatRelativeTime, formatTime } from './date';
|
|
5
5
|
export { addDays, diffMs, formatDateDDMMMYYYY, formatDateISO, formatDatePattern, formatTime12h, formatTimeInWindowsZone, formatTimeInZone, isDateAfter, isDateBefore, isSameDay, startOfDay } from './dateMath';
|
|
6
|
-
export type { FormatterConfig, NumberGrouping, ZoneMode } from './formatConfig';
|
|
6
|
+
export type { DateOrder, FormatterConfig, NumberGrouping, NumberStyle, ZoneMode } from './formatConfig';
|
|
7
7
|
export { configureFormatters, getFormatterConfig } from './formatConfig';
|
|
8
8
|
export type { DateValue, FormatDateOptions, FormatDateTimeOptions, FormatMinorOptions, FormatNumberOptions, FormatPercentOptions, FormatRelativeOptions, FormatTimeOptions, ZoneOption } from './house';
|
|
9
9
|
export { formatMinor, formatRelative } from './house';
|
|
@@ -4,7 +4,8 @@ import { type FormatNumberOptions, type FormatPercentOptions } from './house';
|
|
|
4
4
|
* formatter runs (`./house`: no Intl, the configured grouping and empty
|
|
5
5
|
* placeholder, a numeric string read as its number). With positional
|
|
6
6
|
* arguments the original Intl formatter runs, unchanged, returning '' for
|
|
7
|
-
* missing input
|
|
7
|
+
* missing input; a configured `numberStyle` still sets its decimal mark and
|
|
8
|
+
* group separator.
|
|
8
9
|
*/
|
|
9
10
|
/** "1,23,456.79": the configured grouping, up to three decimals by default. */
|
|
10
11
|
export declare function formatNumber(value: number | string | null | undefined, options?: FormatNumberOptions): string;
|
|
@@ -53,7 +53,7 @@ export type { DeepLinkConfig, DeepLinkRoute, ParsedLink } from './deepLink';
|
|
|
53
53
|
export { DeepLink, parseDeepLink, useDeepLink } from './deepLink';
|
|
54
54
|
export type { ApiError } from './errors';
|
|
55
55
|
export { apiErrorMessage, CONTRACT_ERROR_CODE, extractApiError, isApiError, isNoResponse, NETWORK_CODE, OFFLINE_MESSAGE, REQUEST_CANCELED_CODE, SERVER_FAILURE_MESSAGE, TIMEOUT_CODE, TIMEOUT_MESSAGE, toFieldPath, UNEXPECTED_MESSAGE } from './errors';
|
|
56
|
-
export type { DateInput, DateStyle, DateValue, FormatCurrencyOptions, FormatDateOptions, FormatDateTimeOptions, FormatMinorOptions, FormatNumberOptions, FormatPercentOptions, FormatPhoneOptions, FormatRelativeOptions, FormatTimeOptions, FormatterConfig, NumberGrouping, PhoneCountry, PhoneCountryEntry, PhoneNumber, PhoneNumberType, PhoneParts, PhoneValidationKind, TimeStyle, ZoneMode, ZoneOption } from './formatters';
|
|
56
|
+
export type { DateInput, DateOrder, DateStyle, DateValue, FormatCurrencyOptions, FormatDateOptions, FormatDateTimeOptions, FormatMinorOptions, FormatNumberOptions, FormatPercentOptions, FormatPhoneOptions, FormatRelativeOptions, FormatTimeOptions, FormatterConfig, NumberGrouping, NumberStyle, PhoneCountry, PhoneCountryEntry, PhoneNumber, PhoneNumberType, PhoneParts, PhoneValidationKind, TimeStyle, ZoneMode, ZoneOption } from './formatters';
|
|
57
57
|
export { AsYouType, addDays, clampNationalNumber, configureFormatters, countryFlagEmoji, detectPhoneCountry, diffMs, formatCompactNumber, formatCurrency, formatDate, formatDateDDMMMYYYY, formatDateISO, formatDatePattern, formatDateTime, formatMinor, formatNumber, formatPercent, formatPhone, formatPhoneAsTyped, formatRelative, formatRelativeTime, formatTime, formatTime12h, formatTimeInWindowsZone, formatTimeInZone, getCountries, getCountryCallingCode, getFormatterConfig, getInitials, getPhoneCountries, isDateAfter, isDateBefore, isSameDay, isSupportedCountry, isValidNationalNumber, isValidPhoneNumber, maxNationalNumberLength, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString, splitPhoneNumber, startOfDay, validatePhoneNumberLength } from './formatters';
|
|
58
58
|
export type { InitConfig } from './initSDK';
|
|
59
59
|
export { initWebority } from './initSDK';
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export type PermissionKind = 'camera' | 'microphone' | 'photos' | 'photosAdd' | 'mediaLibrary' | 'location' | 'locationAlways' | 'contacts' | 'calendar' | 'reminders' | 'notifications' | 'bluetooth' | 'storage';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* `undetermined`: never asked, so a request shows the system prompt. `denied`: refused,
|
|
4
|
+
* and a request can still show the prompt (Android after one refusal). `blocked`: the
|
|
5
|
+
* system will not show the prompt again; only Settings can change it.
|
|
6
|
+
*/
|
|
7
|
+
export type PermissionStatus = 'unavailable' | 'undetermined' | 'denied' | 'limited' | 'granted' | 'blocked';
|
|
3
8
|
/** The shared response shape every Expo permission function returns. */
|
|
4
9
|
interface ExpoPermissionResponse {
|
|
5
10
|
status: 'granted' | 'denied' | 'undetermined';
|
|
@@ -40,7 +45,7 @@ export declare const Permissions: {
|
|
|
40
45
|
request: (kind: PermissionKind) => Promise<PermissionStatus>;
|
|
41
46
|
/** Convenience: returns true when the permission is `granted` or `limited`. */
|
|
42
47
|
isAuthorized: (kind: PermissionKind) => Promise<boolean>;
|
|
43
|
-
/** Convenience: check, and request only
|
|
48
|
+
/** Convenience: check, and request only when the status is `undetermined` or `denied`. */
|
|
44
49
|
ensure: (kind: PermissionKind) => Promise<PermissionStatus>;
|
|
45
50
|
openSettings: () => Promise<boolean>;
|
|
46
51
|
};
|
|
@@ -97,6 +97,7 @@ export interface PushState {
|
|
|
97
97
|
interface PermissionResponseLike {
|
|
98
98
|
status: 'granted' | 'denied' | 'undetermined';
|
|
99
99
|
granted: boolean;
|
|
100
|
+
canAskAgain: boolean;
|
|
100
101
|
}
|
|
101
102
|
interface SubscriptionLike {
|
|
102
103
|
remove: () => void;
|
|
@@ -219,7 +220,8 @@ export declare const initPush: (next: PushConfig) => void;
|
|
|
219
220
|
* `config.register`, then re-registers whenever the OS rotates the token.
|
|
220
221
|
* With `{ prompt: false }` it never shows the permission prompt: a phone
|
|
221
222
|
* already granted registers, and any other resolves with its status
|
|
222
|
-
* (`
|
|
223
|
+
* (`undetermined` when the person has not been asked yet, `denied` when refused
|
|
224
|
+
* and the prompt can still show, `blocked` when only Settings can turn it on).
|
|
223
225
|
*/
|
|
224
226
|
export declare const enablePush: ({ prompt }?: EnablePushOptions) => Promise<PushStatus>;
|
|
225
227
|
/**
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* The push permission values, as runtime constants an app can compare against.
|
|
3
|
+
* `unknown`: not read yet. `undetermined`: never asked. `denied`: refused, and a
|
|
4
|
+
* request can still show the prompt. `blocked`: refused for good, only Settings
|
|
5
|
+
* can turn it on. Matches `PermissionStatus` in the permissions module.
|
|
6
|
+
*/
|
|
2
7
|
export declare const PUSH_STATUS: {
|
|
3
8
|
readonly unknown: "unknown";
|
|
9
|
+
readonly undetermined: "undetermined";
|
|
4
10
|
readonly granted: "granted";
|
|
5
11
|
readonly denied: "denied";
|
|
12
|
+
readonly blocked: "blocked";
|
|
6
13
|
readonly unavailable: "unavailable";
|
|
7
14
|
};
|
|
8
15
|
export type PushStatus = (typeof PUSH_STATUS)[keyof typeof PUSH_STATUS];
|
|
@@ -25,6 +25,8 @@ export interface FormatCurrencyOptions extends Omit<Intl.NumberFormatOptions, 's
|
|
|
25
25
|
* options: "₹1,50,000" for 150000, "₹1,234.50" for 1234.5, and `''` for a missing amount.
|
|
26
26
|
* Once the app configures a locale (`configureFormatters({ locale })`), the amount is
|
|
27
27
|
* written in that locale and a missing amount prints the configured placeholder ("-").
|
|
28
|
+
* A configured `numberStyle` sets the decimal mark and group separator; the locale keeps
|
|
29
|
+
* its group sizes and symbol placement ("₹1.50.000,50" for `'CommaWithPointGroups'`).
|
|
28
30
|
* A numeric string reads as its number. For money the API carries in minor units (paise),
|
|
29
31
|
* use `formatMinor`.
|
|
30
32
|
*
|
|
@@ -12,12 +12,35 @@
|
|
|
12
12
|
* "8:05 PM", "1,23,456.79"). Configuring a locale hands the words and
|
|
13
13
|
* separators to Intl for that locale: month names, digit separators, the
|
|
14
14
|
* 12- or 24-hour clock and its AM/PM casing, zone names and relative phrases.
|
|
15
|
-
* The date order stays DD-MMM-YYYY either way.
|
|
15
|
+
* The date order stays DD-MMM-YYYY either way, unless a date order is set.
|
|
16
|
+
*
|
|
17
|
+
* Personal style: a product that lets a person choose how numbers and dates
|
|
18
|
+
* read sets `numberStyle` and `dateOrder`. The number style swaps only the
|
|
19
|
+
* decimal mark and the group separator, so the locale's group sizes (en-IN's
|
|
20
|
+
* 12,34,567) and its currency symbol placement stay. The date order changes
|
|
21
|
+
* only the date; the time of day, the zone and relative phrases are untouched.
|
|
16
22
|
*/
|
|
17
23
|
/** `'IST'`: every instant in India Standard Time. `'viewer'`: the device or browser zone, labelled. */
|
|
18
24
|
export type ZoneMode = 'IST' | 'viewer';
|
|
19
25
|
/** How the integer part of a number is grouped. */
|
|
20
26
|
export type NumberGrouping = 'indian' | 'international' | 'none';
|
|
27
|
+
/**
|
|
28
|
+
* The decimal mark and group separator of every number: `'PointWithCommaGroups'` "1,234.5",
|
|
29
|
+
* `'CommaWithPointGroups'` "1.234,5", `'CommaWithSpaceGroups'` "1 234,5", `'PointWithSpaceGroups'`
|
|
30
|
+
* "1 234.5". The space is a no-break space (U+00A0), so a number never wraps.
|
|
31
|
+
*/
|
|
32
|
+
export type NumberStyle = 'PointWithCommaGroups' | 'CommaWithPointGroups' | 'CommaWithSpaceGroups' | 'PointWithSpaceGroups';
|
|
33
|
+
/**
|
|
34
|
+
* The order of every date: `'DayMonthNameYear'` "09-Oct-2026" (the house order, month name from the
|
|
35
|
+
* locale when one is configured), `'DayMonthYear'` "09/10/2026", `'MonthDayYear'` "10/09/2026",
|
|
36
|
+
* `'YearMonthDay'` "2026-10-09".
|
|
37
|
+
*/
|
|
38
|
+
export type DateOrder = 'DayMonthNameYear' | 'DayMonthYear' | 'MonthDayYear' | 'YearMonthDay';
|
|
39
|
+
/** The two characters a number style puts in a number. */
|
|
40
|
+
export interface NumberSeparators {
|
|
41
|
+
decimal: string;
|
|
42
|
+
group: string;
|
|
43
|
+
}
|
|
21
44
|
export interface FormatterConfig {
|
|
22
45
|
/** Default zone for every date and time formatter. */
|
|
23
46
|
zone: ZoneMode;
|
|
@@ -30,11 +53,17 @@ export interface FormatterConfig {
|
|
|
30
53
|
locale: string;
|
|
31
54
|
/** What every formatter returns for a missing or unreadable value. */
|
|
32
55
|
empty: string;
|
|
56
|
+
/** The person's number style. Unset, the separators are the house text's or the configured locale's. */
|
|
57
|
+
numberStyle?: NumberStyle;
|
|
58
|
+
/** The person's date order. Unset, dates read DD-MMM-YYYY. */
|
|
59
|
+
dateOrder?: DateOrder;
|
|
33
60
|
}
|
|
34
61
|
/**
|
|
35
|
-
* Set the zone mode, locale
|
|
36
|
-
*
|
|
37
|
-
* Passing nothing restores the defaults (IST,
|
|
62
|
+
* Set the zone mode, locale, empty placeholder, number style or date order for the whole app.
|
|
63
|
+
* Call it at startup, and again when the person changes their number style or date order; a key
|
|
64
|
+
* left out (or undefined) keeps its current value. Passing nothing restores the defaults (IST,
|
|
65
|
+
* en-IN, "-", house text, no number style or date order). An unknown number style or date order
|
|
66
|
+
* throws a RangeError, so a bad stored preference fails where it is applied.
|
|
38
67
|
*/
|
|
39
68
|
export declare const configureFormatters: (config?: Partial<FormatterConfig>) => void;
|
|
40
69
|
/** The settings in force, as a copy. */
|
|
@@ -45,4 +74,11 @@ export declare const isFormatterConfigured: (key: keyof FormatterConfig) => bool
|
|
|
45
74
|
export declare const configuredLocale: () => string | null;
|
|
46
75
|
/** The grouping a locale implies: Indian for a locale whose region is IN. */
|
|
47
76
|
export declare const groupingForLocale: (locale: string) => NumberGrouping;
|
|
77
|
+
/** The configured number style's separators, else null (the house text's or the locale's own). */
|
|
78
|
+
export declare const numberSeparators: () => NumberSeparators | null;
|
|
79
|
+
/**
|
|
80
|
+
* `format.format(n)`, with the configured number style's decimal mark and group separator in place
|
|
81
|
+
* of the locale's. Only those two parts change, so group sizes, signs and symbols stay the locale's.
|
|
82
|
+
*/
|
|
83
|
+
export declare const styledNumber: (format: Intl.NumberFormat, n: number) => string;
|
|
48
84
|
//# sourceMappingURL=formatConfig.d.ts.map
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
* from Intl for that locale and the date order stays DD-MMM-YYYY. For en-IN in the viewer zone:
|
|
27
27
|
* "08-Sept-2026", "08:05 pm", "08-Sept-2026, 08:05 pm IST", "yesterday", "12,34,567.891",
|
|
28
28
|
* "₹1,50,000". For de-DE: "08-Sept-2026", "20:05", "1.234.567,891".
|
|
29
|
+
*
|
|
30
|
+
* A configured `numberStyle` puts its decimal mark and group separator in every number and amount,
|
|
31
|
+
* whichever path wrote it: "1.23.456,789" for `'CommaWithPointGroups'` with the house text. A
|
|
32
|
+
* configured `dateOrder` other than DD-MMM-YYYY writes the date as digits from the wall clock,
|
|
33
|
+
* in every locale: "08/04/2026", "04/08/2026", "2026-04-08".
|
|
29
34
|
*/
|
|
30
35
|
import { type NumberGrouping, type ZoneMode } from './formatConfig.js';
|
|
31
36
|
/** A date the house formatters accept; null, undefined and "" read as missing. */
|
|
@@ -102,8 +107,8 @@ export interface FormatMinorOptions {
|
|
|
102
107
|
empty?: string;
|
|
103
108
|
}
|
|
104
109
|
/**
|
|
105
|
-
* "08-Apr-2026". A bare calendar date ("2026-04-08")
|
|
106
|
-
* an instant shows its day in the configured zone.
|
|
110
|
+
* "08-Apr-2026", or the configured date order. A bare calendar date ("2026-04-08")
|
|
111
|
+
* always shows as that day; an instant shows its day in the configured zone.
|
|
107
112
|
*/
|
|
108
113
|
export declare const formatDate: (value: DateValue, options?: FormatDateOptions) => string;
|
|
109
114
|
/** "8:05 PM" in IST, "8:05 PM GMT-4" in the viewer's zone; "20:05" for a configured locale with a 24-hour clock. */
|
|
@@ -3,7 +3,7 @@ export { formatCurrency } from './currency.js';
|
|
|
3
3
|
export type { DateInput, DateStyle, TimeStyle } from './date.js';
|
|
4
4
|
export { formatDate, formatDateTime, formatRelativeTime, formatTime } from './date.js';
|
|
5
5
|
export { addDays, diffMs, formatDateDDMMMYYYY, formatDateISO, formatDatePattern, formatTime12h, formatTimeInWindowsZone, formatTimeInZone, isDateAfter, isDateBefore, isSameDay, startOfDay } from './dateMath.js';
|
|
6
|
-
export type { FormatterConfig, NumberGrouping, ZoneMode } from './formatConfig.js';
|
|
6
|
+
export type { DateOrder, FormatterConfig, NumberGrouping, NumberStyle, ZoneMode } from './formatConfig.js';
|
|
7
7
|
export { configureFormatters, getFormatterConfig } from './formatConfig.js';
|
|
8
8
|
export type { DateValue, FormatDateOptions, FormatDateTimeOptions, FormatMinorOptions, FormatNumberOptions, FormatPercentOptions, FormatRelativeOptions, FormatTimeOptions, ZoneOption } from './house.js';
|
|
9
9
|
export { formatMinor, formatRelative } from './house.js';
|
|
@@ -4,7 +4,8 @@ import { type FormatNumberOptions, type FormatPercentOptions } from './house.js'
|
|
|
4
4
|
* formatter runs (`./house`: no Intl, the configured grouping and empty
|
|
5
5
|
* placeholder, a numeric string read as its number). With positional
|
|
6
6
|
* arguments the original Intl formatter runs, unchanged, returning '' for
|
|
7
|
-
* missing input
|
|
7
|
+
* missing input; a configured `numberStyle` still sets its decimal mark and
|
|
8
|
+
* group separator.
|
|
8
9
|
*/
|
|
9
10
|
/** "1,23,456.79": the configured grouping, up to three decimals by default. */
|
|
10
11
|
export declare function formatNumber(value: number | string | null | undefined, options?: FormatNumberOptions): string;
|
|
@@ -53,7 +53,7 @@ export type { DeepLinkConfig, DeepLinkRoute, ParsedLink } from './deepLink/index
|
|
|
53
53
|
export { DeepLink, parseDeepLink, useDeepLink } from './deepLink/index.js';
|
|
54
54
|
export type { ApiError } from './errors/index.js';
|
|
55
55
|
export { apiErrorMessage, CONTRACT_ERROR_CODE, extractApiError, isApiError, isNoResponse, NETWORK_CODE, OFFLINE_MESSAGE, REQUEST_CANCELED_CODE, SERVER_FAILURE_MESSAGE, TIMEOUT_CODE, TIMEOUT_MESSAGE, toFieldPath, UNEXPECTED_MESSAGE } from './errors/index.js';
|
|
56
|
-
export type { DateInput, DateStyle, DateValue, FormatCurrencyOptions, FormatDateOptions, FormatDateTimeOptions, FormatMinorOptions, FormatNumberOptions, FormatPercentOptions, FormatPhoneOptions, FormatRelativeOptions, FormatTimeOptions, FormatterConfig, NumberGrouping, PhoneCountry, PhoneCountryEntry, PhoneNumber, PhoneNumberType, PhoneParts, PhoneValidationKind, TimeStyle, ZoneMode, ZoneOption } from './formatters/index.js';
|
|
56
|
+
export type { DateInput, DateOrder, DateStyle, DateValue, FormatCurrencyOptions, FormatDateOptions, FormatDateTimeOptions, FormatMinorOptions, FormatNumberOptions, FormatPercentOptions, FormatPhoneOptions, FormatRelativeOptions, FormatTimeOptions, FormatterConfig, NumberGrouping, NumberStyle, PhoneCountry, PhoneCountryEntry, PhoneNumber, PhoneNumberType, PhoneParts, PhoneValidationKind, TimeStyle, ZoneMode, ZoneOption } from './formatters/index.js';
|
|
57
57
|
export { AsYouType, addDays, clampNationalNumber, configureFormatters, countryFlagEmoji, detectPhoneCountry, diffMs, formatCompactNumber, formatCurrency, formatDate, formatDateDDMMMYYYY, formatDateISO, formatDatePattern, formatDateTime, formatMinor, formatNumber, formatPercent, formatPhone, formatPhoneAsTyped, formatRelative, formatRelativeTime, formatTime, formatTime12h, formatTimeInWindowsZone, formatTimeInZone, getCountries, getCountryCallingCode, getFormatterConfig, getInitials, getPhoneCountries, isDateAfter, isDateBefore, isSameDay, isSupportedCountry, isValidNationalNumber, isValidPhoneNumber, maxNationalNumberLength, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString, splitPhoneNumber, startOfDay, validatePhoneNumberLength } from './formatters/index.js';
|
|
58
58
|
export type { InitConfig } from './initSDK.js';
|
|
59
59
|
export { initWebority } from './initSDK.js';
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export type PermissionKind = 'camera' | 'microphone' | 'photos' | 'photosAdd' | 'mediaLibrary' | 'location' | 'locationAlways' | 'contacts' | 'calendar' | 'reminders' | 'notifications' | 'bluetooth' | 'storage';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* `undetermined`: never asked, so a request shows the system prompt. `denied`: refused,
|
|
4
|
+
* and a request can still show the prompt (Android after one refusal). `blocked`: the
|
|
5
|
+
* system will not show the prompt again; only Settings can change it.
|
|
6
|
+
*/
|
|
7
|
+
export type PermissionStatus = 'unavailable' | 'undetermined' | 'denied' | 'limited' | 'granted' | 'blocked';
|
|
3
8
|
/** The shared response shape every Expo permission function returns. */
|
|
4
9
|
interface ExpoPermissionResponse {
|
|
5
10
|
status: 'granted' | 'denied' | 'undetermined';
|
|
@@ -40,7 +45,7 @@ export declare const Permissions: {
|
|
|
40
45
|
request: (kind: PermissionKind) => Promise<PermissionStatus>;
|
|
41
46
|
/** Convenience: returns true when the permission is `granted` or `limited`. */
|
|
42
47
|
isAuthorized: (kind: PermissionKind) => Promise<boolean>;
|
|
43
|
-
/** Convenience: check, and request only
|
|
48
|
+
/** Convenience: check, and request only when the status is `undetermined` or `denied`. */
|
|
44
49
|
ensure: (kind: PermissionKind) => Promise<PermissionStatus>;
|
|
45
50
|
openSettings: () => Promise<boolean>;
|
|
46
51
|
};
|
|
@@ -97,6 +97,7 @@ export interface PushState {
|
|
|
97
97
|
interface PermissionResponseLike {
|
|
98
98
|
status: 'granted' | 'denied' | 'undetermined';
|
|
99
99
|
granted: boolean;
|
|
100
|
+
canAskAgain: boolean;
|
|
100
101
|
}
|
|
101
102
|
interface SubscriptionLike {
|
|
102
103
|
remove: () => void;
|
|
@@ -219,7 +220,8 @@ export declare const initPush: (next: PushConfig) => void;
|
|
|
219
220
|
* `config.register`, then re-registers whenever the OS rotates the token.
|
|
220
221
|
* With `{ prompt: false }` it never shows the permission prompt: a phone
|
|
221
222
|
* already granted registers, and any other resolves with its status
|
|
222
|
-
* (`
|
|
223
|
+
* (`undetermined` when the person has not been asked yet, `denied` when refused
|
|
224
|
+
* and the prompt can still show, `blocked` when only Settings can turn it on).
|
|
223
225
|
*/
|
|
224
226
|
export declare const enablePush: ({ prompt }?: EnablePushOptions) => Promise<PushStatus>;
|
|
225
227
|
/**
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* The push permission values, as runtime constants an app can compare against.
|
|
3
|
+
* `unknown`: not read yet. `undetermined`: never asked. `denied`: refused, and a
|
|
4
|
+
* request can still show the prompt. `blocked`: refused for good, only Settings
|
|
5
|
+
* can turn it on. Matches `PermissionStatus` in the permissions module.
|
|
6
|
+
*/
|
|
2
7
|
export declare const PUSH_STATUS: {
|
|
3
8
|
readonly unknown: "unknown";
|
|
9
|
+
readonly undetermined: "undetermined";
|
|
4
10
|
readonly granted: "granted";
|
|
5
11
|
readonly denied: "denied";
|
|
12
|
+
readonly blocked: "blocked";
|
|
6
13
|
readonly unavailable: "unavailable";
|
|
7
14
|
};
|
|
8
15
|
export type PushStatus = (typeof PUSH_STATUS)[keyof typeof PUSH_STATUS];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/mobile-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
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",
|