@webority/mobile-core 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +3 -2
  2. package/lib/commonjs/api/userClient.js +1 -1
  3. package/lib/commonjs/formatters/currency.js +1 -1
  4. package/lib/commonjs/formatters/formatConfig.js +1 -1
  5. package/lib/commonjs/formatters/house.js +1 -1
  6. package/lib/commonjs/formatters/number.js +1 -1
  7. package/lib/commonjs/logger/index.js +1 -1
  8. package/lib/commonjs/permissions/index.js +1 -1
  9. package/lib/commonjs/push/push.js +1 -1
  10. package/lib/commonjs/push/status.js +1 -1
  11. package/lib/module/api/userClient.js +1 -1
  12. package/lib/module/formatters/currency.js +1 -1
  13. package/lib/module/formatters/formatConfig.js +1 -1
  14. package/lib/module/formatters/house.js +1 -1
  15. package/lib/module/formatters/number.js +1 -1
  16. package/lib/module/logger/index.js +1 -1
  17. package/lib/module/permissions/index.js +1 -1
  18. package/lib/module/push/push.js +1 -1
  19. package/lib/module/push/status.js +1 -1
  20. package/lib/typescript/commonjs/formatters/currency.d.ts +2 -0
  21. package/lib/typescript/commonjs/formatters/formatConfig.d.ts +40 -4
  22. package/lib/typescript/commonjs/formatters/house.d.ts +7 -2
  23. package/lib/typescript/commonjs/formatters/index.d.ts +1 -1
  24. package/lib/typescript/commonjs/formatters/number.d.ts +2 -1
  25. package/lib/typescript/commonjs/index.d.ts +1 -1
  26. package/lib/typescript/commonjs/permissions/index.d.ts +7 -2
  27. package/lib/typescript/commonjs/push/push.d.ts +3 -1
  28. package/lib/typescript/commonjs/push/status.d.ts +8 -1
  29. package/lib/typescript/module/formatters/currency.d.ts +2 -0
  30. package/lib/typescript/module/formatters/formatConfig.d.ts +40 -4
  31. package/lib/typescript/module/formatters/house.d.ts +7 -2
  32. package/lib/typescript/module/formatters/index.d.ts +1 -1
  33. package/lib/typescript/module/formatters/number.d.ts +2 -1
  34. package/lib/typescript/module/index.d.ts +1 -1
  35. package/lib/typescript/module/permissions/index.d.ts +7 -2
  36. package/lib/typescript/module/push/push.d.ts +3 -1
  37. package/lib/typescript/module/push/status.d.ts +8 -1
  38. 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 (`unknown` when the person has not
87
- been asked yet, `denied` when refused). Call it at sign-in, and call `enablePush()` when the
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)&&(e._endReplacement=(0,_tokenRefresh.beginSessionReplacement)()),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
+ "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 e=r<0?"-":"",n=Math.abs(r).toFixed(t),[i,o]=n.split("."),m=i.length>3?i.slice(-3):i,u=i.length>3?i.slice(0,-3):"";return e+(u?u.replace(/\B(?=(\d{2})+(?!\d))/g,",")+","+m:m)+(o?`.${o}`:"")},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:u=((0,_formatConfig.isFormatterConfigured)("locale")||(0,_formatConfig.isFormatterConfigured)("empty")?(0,_formatConfig.getFormatterConfig)().empty:""),...a}=t,c=toAmount(r);if(null===c)return u;if(hasIntlNumber())try{const r=o??currencyDigits(n,e),t=i??(Number.isInteger(c)?0:r),u=(0,_intlCache.numberFormat)(n,{...a,style:"currency",currency:e,minimumFractionDigits:t,maximumFractionDigits:Math.max(t,r)}).format(c);return m?u.replace(/[^\d,.\s\-+]/g,"").trim():u}catch{}const s=indianGroupingFallback(c,i??(Number.isInteger(c)?0:2));return m?s:"INR"===e?`₹${s}`:`${e} ${s}`};exports.formatCurrency=formatCurrency;
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 o of Object.keys(e)){const r=e[o];void 0!==r&&(current={...current,[o]:r},configured.add(o))}};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;
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?"+":"-",n=Math.abs(t),o=n%60;return`GMT${e}${Math.floor(n/60)}${0===o?"":`:${pad2(o)}`}`},shifted=(t,e,n)=>{const o=new Date(t.getTime()+6e4*e);return{year:o.getUTCFullYear(),month:o.getUTCMonth(),day:o.getUTCDate(),hour:o.getUTCHours(),minute:o.getUTCMinutes(),label:n}},inIanaZone=(t,e)=>{const n=(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(n.find(e=>e.type===t)?.value??"",10),o=read("year"),r=read("month")-1,i=read("day"),a=read("hour")%24,m=read("minute"),l=Date.UTC(o,r,i,a,m),u=Math.round((l-6e4*Math.floor(t.getTime()/6e4))/6e4);return{year:o,month:r,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}`,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,o)=>labelled(n,o)?`${t} ${e.label}`:t,intlZone=t=>{if("viewer"!==t)return IST_NAMES.includes(t)?"Asia/Kolkata":t},localeDayMonthYear=(t,e,n)=>{const o=(0,_intlCache.dateTimeFormat)(e,{day:"2-digit",month:"short",year:"numeric",timeZone:n}).formatToParts(t),part=t=>o.find(e=>e.type===t)?.value??"";return`${part("day")}-${part("month").replace(".","")}-${part("year")}`},localeClock=(t,e,n,o)=>(0,_intlCache.dateTimeFormat)(e,{hour:"2-digit",minute:"2-digit",timeZone:intlZone(n),timeZoneName:labelled(n,o.zoneLabel)?"short":void 0,hourCycle:void 0===o.hourCycle?void 0:24===o.hourCycle?"h23":"h12"}).format(t),formatDate=(t,e={})=>{const n=toInstant(t);if(!n)return emptyOf(e.empty);const o=isDateOnly(t)?"UTC":e.zone??(0,_formatConfig.getFormatterConfig)().zone,r=(0,_formatConfig.configuredLocale)();return r?localeDayMonthYear(n,r,intlZone(o)):dayMonthYear(wallClock(n,o))};exports.formatDate=formatDate;const formatTime=(t,e={})=>{const n=toInstant(t);if(!n)return emptyOf(e.empty);const o=e.zone??(0,_formatConfig.getFormatterConfig)().zone,r=(0,_formatConfig.configuredLocale)();if(r)return localeClock(n,r,o,e);const i=wallClock(n,o);return withLabel(clockTime(i,hourCycleOf(e)),i,o,e.zoneLabel)};exports.formatTime=formatTime;const formatDateTime=(t,e={})=>{const n=toInstant(t);if(!n)return emptyOf(e.empty);const o=e.zone??(0,_formatConfig.getFormatterConfig)().zone,r=(0,_formatConfig.configuredLocale)();if(r)return`${localeDayMonthYear(n,r,intlZone(o))}, ${localeClock(n,r,o,e)}`;const i=wallClock(n,o);return withLabel(`${dayMonthYear(i)}, ${clockTime(i,hourCycleOf(e))}`,i,o,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 n=toInstant(t),o=toInstant(e.now??Date.now());if(!n||!o)return emptyOf(e.empty);const r=n.getTime()-o.getTime(),i=Math.abs(r),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,n]=INTL_UNITS.find(([,t])=>i>=t)??["second",1e3];return t.format(Math.round(r/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 r<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}`),groupInteger=(t,e)=>{if("none"===e||t.length<=3)return t;if("international"===e)return t.replace(/\B(?=(\d{3})+(?!\d))/g,",");return`${t.slice(0,-3).replace(/\B(?=(\d{2})+(?!\d))/g,",")},${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 n=Math.min(e,15);return shiftDecimal(Math.round(shiftDecimal(t,n)),-n).toFixed(n)},decimalText=(t,e,n,o)=>{const r=Math.max(clampDigits(n),clampDigits(e)),i=clampDigits(e),a=plainDigits(Math.abs(t),r),[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=groupInteger(m,o)+(u?`.${u}`:"");return t<0&&/[1-9]/.test(a)?`-${c}`:c},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:o,scale:r,...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 n=clampDigits(t);return{minimumFractionDigits:n,maximumFractionDigits:Math.max(n,clampDigits(e))}},groupingOption=t=>"none"===t?{useGrouping:!1}:{},formatNumber=(t,e={})=>{const n=toNumber(t);if(null===n)return emptyOf(e.empty);const o=intlNumberOptions(e);if(o)return(0,_intlCache.numberFormat)(localeOf(e),o).format(n);const r=intlTextLocale(e);return r?(0,_intlCache.numberFormat)(r,{...fractionDigits(e.minimumFractionDigits??0,e.maximumFractionDigits??3),...groupingOption(e.grouping)}).format(n):decimalText(n,e.minimumFractionDigits??0,e.maximumFractionDigits??3,e.grouping??(0,_formatConfig.groupingForLocale)(localeOf(e)))};exports.formatNumber=formatNumber;const formatPercent=(t,e={})=>{const n=toNumber(t);if(null===n)return emptyOf(e.empty);const o=intlNumberOptions(e);if(o){const t="percent"===e.scale?shiftDecimal(n,-2):n;return(0,_intlCache.numberFormat)(localeOf(e),{style:"percent",...o}).format(t)}const r=intlTextLocale(e);if(r){const t="percent"===e.scale?shiftDecimal(n,-2):n;return(0,_intlCache.numberFormat)(r,{style:"percent",...fractionDigits(e.minimumFractionDigits??0,e.maximumFractionDigits??e.minimumFractionDigits??0),...groupingOption(e.grouping)}).format(t)}const i="percent"===e.scale?n:shiftDecimal(n,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 n=toNumber(t);if(null===n)return emptyOf(e.empty);const o=(e.currency??"INR").toUpperCase(),r=MINOR_DIGITS[o]??2,i=Math.round(Math.abs(n)),a=String(i).padStart(r+1,"0"),m=a.slice(0,a.length-r);let l=a.slice(a.length-r);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-r)||"0"}`);return(0,_intlCache.numberFormat)(u,{...!1===e.symbol?{}:{style:"currency",currency:o},...fractionDigits(l?r:0,r),...groupingOption(e.grouping)}).format(t)}catch{}const c=e.grouping??("INR"===o?"indian":"international"),s=groupInteger(m,c)+(l?`.${l}`:""),f=n<0&&0!==i?"-":"";if(!1===e.symbol)return`${f}${s}`;const g=SYMBOLS[o];return g?`${f}${g}${s}`:`${f}${o} ${s}`};exports.formatMinor=formatMinor;
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 n="number"==typeof e?e:void 0,o=t;if(null==o||Number.isNaN(o))return"";if(hasIntlNumber())try{const t={};return null!=n&&(t.minimumFractionDigits=n,t.maximumFractionDigits=n),(0,_intlCache.numberFormat)(r??"en-IN",t).format(o)}catch{}return null!=n?o.toFixed(n):String(o)}function formatPercent(t,e,r,n){if("number"!=typeof e&&void 0===r&&void 0===n)return(0,_house.formatPercent)(t,e);const o="number"==typeof e?e:0,m=t;if(null==m||Number.isNaN(m))return"";const i=r??1?m:m/100;if(hasIntlNumber())try{return(0,_intlCache.numberFormat)(n??"en-IN",{style:"percent",minimumFractionDigits:o,maximumFractionDigits:o}).format(i)}catch{}return`${(100*i).toFixed(o)}%`}const formatCompactNumber=(t,e="en-IN")=>{if(null==t||Number.isNaN(t))return"";if(hasIntlNumber())try{return(0,_intlCache.numberFormat)(e,{notation:"compact",maximumFractionDigits:1}).format(t)}catch{}const r=Math.abs(t),n=t<0?"-":"";return r>=1e7?`${n}${(r/1e7).toFixed(1)}Cr`:r>=1e5?`${n}${(r/1e5).toFixed(1)}L`:r>=1e3?`${n}${(r/1e3).toFixed(1)}K`:`${t}`};exports.formatCompactNumber=formatCompactNumber;
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:"",GRAY:"",BLUE:"",YELLOW:"",RED_BOLD:""},LogLevels={DEBUG:{level:"debug",color:Colors.GRAY},INFO:{level:"info",color:Colors.BLUE},WARN:{level:"warn",color:Colors.YELLOW},ERROR:{level:"error",color:Colors.RED_BOLD}},isLogLevelAllowed=e=>{const r=["debug","info","warn","error"],o=(0,_index.getConfigValue)("logLevel","info");return r.indexOf(e)>=r.indexOf(o)},isEnabled=()=>(0,_index.getConfigValue)("loggingEnabled",!0);let remote=null;const setRemoteLogger=e=>{remote=e};exports.setRemoteLogger=setRemoteLogger;const safe=e=>{if(e)try{e()}catch{}},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:"",GRAY:"",BLUE:"",YELLOW:"",RED_BOLD:""},LogLevels={DEBUG:{level:"debug",color:Colors.GRAY},INFO:{level:"info",color:Colors.BLUE},WARN:{level:"warn",color:Colors.YELLOW},ERROR:{level:"error",color:Colors.RED_BOLD}},isLogLevelAllowed=e=>{const r=["debug","info","warn","error"],o=(0,_index.getConfigValue)("logLevel","info");return r.indexOf(e)>=r.indexOf(o)},isEnabled=()=>(0,_index.getConfigValue)("loggingEnabled",!0);let remote=null;const setRemoteLogger=e=>{remote=e};exports.setRemoteLogger=setRemoteLogger;const safe=e=>{if(e)try{e()}catch{}},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,s)=>{registry.set(e,s)};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":"denied":"unavailable",checkPermission=async e=>{if(backend)return backend.check(e);const s=resolveExpoModule(e);if(!s)return"unavailable";try{return toStatus(await s.check())}catch(s){return _index.Logger.error(`[permissions] check(${e}) failed`,s),"unavailable"}},requestPermission=async e=>{if(backend)return backend.request(e);const s=resolveExpoModule(e);if(!s)return"unavailable";try{return toStatus(await s.request())}catch(s){return _index.Logger.error(`[permissions] request(${e}) failed`,s),"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 s=await checkPermission(e);return"granted"===s||"limited"===s},ensure:async e=>{const s=await checkPermission(e);return"granted"===s||"limited"===s||"blocked"===s||"unavailable"===s?s:requestPermission(e)},openSettings:openAppSettings};
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":"unknown",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
+ "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)&&(e._endReplacement=beginSessionReplacement()),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
+ "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 e=r<0?"-":"",n=Math.abs(r).toFixed(t),[i,o]=n.split("."),m=i.length>3?i.slice(-3):i,u=i.length>3?i.slice(0,-3):"";return e+(u?u.replace(/\B(?=(\d{2})+(?!\d))/g,",")+","+m:m)+(o?`.${o}`:"")},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=numberFormat(n,{...c,style:"currency",currency:e,minimumFractionDigits:t,maximumFractionDigits:Math.max(t,r)}).format(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
+ "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 o of Object.keys(e)){const r=e[o];void 0!==r&&(current={...current,[o]:r},configured.add(o))}};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";
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),o=n%60;return`GMT${e}${Math.floor(n/60)}${0===o?"":`:${pad2(o)}`}`},shifted=(t,e,n)=>{const o=new Date(t.getTime()+6e4*e);return{year:o.getUTCFullYear(),month:o.getUTCMonth(),day:o.getUTCDate(),hour:o.getUTCHours(),minute:o.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),o=read("year"),r=read("month")-1,i=read("day"),a=read("hour")%24,l=read("minute"),m=Date.UTC(o,r,i,a,l),u=Math.round((m-6e4*Math.floor(t.getTime()/6e4))/6e4);return{year:o,month:r,day:i,hour:a,minute:l,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}`,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,o)=>labelled(n,o)?`${t} ${e.label}`:t,intlZone=t=>{if("viewer"!==t)return IST_NAMES.includes(t)?"Asia/Kolkata":t},localeDayMonthYear=(t,e,n)=>{const o=dateTimeFormat(e,{day:"2-digit",month:"short",year:"numeric",timeZone:n}).formatToParts(t),part=t=>o.find(e=>e.type===t)?.value??"";return`${part("day")}-${part("month").replace(".","")}-${part("year")}`},localeClock=(t,e,n,o)=>dateTimeFormat(e,{hour:"2-digit",minute:"2-digit",timeZone:intlZone(n),timeZoneName:labelled(n,o.zoneLabel)?"short":void 0,hourCycle:void 0===o.hourCycle?void 0:24===o.hourCycle?"h23":"h12"}).format(t);export const formatDate=(t,e={})=>{const n=toInstant(t);if(!n)return emptyOf(e.empty);const o=isDateOnly(t)?"UTC":e.zone??getFormatterConfig().zone,r=configuredLocale();return r?localeDayMonthYear(n,r,intlZone(o)):dayMonthYear(wallClock(n,o))};export const formatTime=(t,e={})=>{const n=toInstant(t);if(!n)return emptyOf(e.empty);const o=e.zone??getFormatterConfig().zone,r=configuredLocale();if(r)return localeClock(n,r,o,e);const i=wallClock(n,o);return withLabel(clockTime(i,hourCycleOf(e)),i,o,e.zoneLabel)};export const formatDateTime=(t,e={})=>{const n=toInstant(t);if(!n)return emptyOf(e.empty);const o=e.zone??getFormatterConfig().zone,r=configuredLocale();if(r)return`${localeDayMonthYear(n,r,intlZone(o))}, ${localeClock(n,r,o,e)}`;const i=wallClock(n,o);return withLabel(`${dayMonthYear(i)}, ${clockTime(i,hourCycleOf(e))}`,i,o,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),o=toInstant(e.now??Date.now());if(!n||!o)return emptyOf(e.empty);const r=n.getTime()-o.getTime(),i=Math.abs(r),a=Intl.RelativeTimeFormat,l=configuredLocale();if((null!==l||!0===e.intl)&&"function"==typeof a){const t=relativeTimeFormat(a,l??getFormatterConfig().locale),[e,n]=INTL_UNITS.find(([,t])=>i>=t)??["second",1e3];return t.format(Math.round(r/n),e)}if(i<6e4)return"just now";const[m,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} ${m}${1===c?"":"s"}`;return r<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}`),groupInteger=(t,e)=>{if("none"===e||t.length<=3)return t;if("international"===e)return t.replace(/\B(?=(\d{3})+(?!\d))/g,",");return`${t.slice(0,-3).replace(/\B(?=(\d{2})+(?!\d))/g,",")},${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,o)=>{const r=Math.max(clampDigits(n),clampDigits(e)),i=clampDigits(e),a=plainDigits(Math.abs(t),r),[l="0",m=""]=a.split(".");let u=m.padEnd(i,"0");for(;u.length>i&&u.endsWith("0");)u=u.slice(0,-1);const c=groupInteger(l,o)+(u?`.${u}`:"");return t<0&&/[1-9]/.test(a)?`-${c}`:c},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:o,scale:r,...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 o=intlNumberOptions(e);if(o)return numberFormat(localeOf(e),o).format(n);const r=intlTextLocale(e);return r?numberFormat(r,{...fractionDigits(e.minimumFractionDigits??0,e.maximumFractionDigits??3),...groupingOption(e.grouping)}).format(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 o=intlNumberOptions(e);if(o){const t="percent"===e.scale?shiftDecimal(n,-2):n;return numberFormat(localeOf(e),{style:"percent",...o}).format(t)}const r=intlTextLocale(e);if(r){const t="percent"===e.scale?shiftDecimal(n,-2):n;return numberFormat(r,{style:"percent",...fractionDigits(e.minimumFractionDigits??0,e.maximumFractionDigits??e.minimumFractionDigits??0),...groupingOption(e.grouping)}).format(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 o=(e.currency??"INR").toUpperCase(),r=MINOR_DIGITS[o]??2,i=Math.round(Math.abs(n)),a=String(i).padStart(r+1,"0"),l=a.slice(0,a.length-r);let m=a.slice(a.length-r);e.dropZeroDecimals&&/^0*$/.test(m)&&(m="");const u=intlTextLocale({grouping:e.grouping});if(u)try{const t=Number(`${n<0&&0!==i?"-":""}${l}.${a.slice(a.length-r)||"0"}`);return numberFormat(u,{...!1===e.symbol?{}:{style:"currency",currency:o},...fractionDigits(m?r:0,r),...groupingOption(e.grouping)}).format(t)}catch{}const c=e.grouping??("INR"===o?"indian":"international"),s=groupInteger(l,c)+(m?`.${m}`:""),g=n<0&&0!==i?"-":"";if(!1===e.symbol)return`${g}${s}`;const f=SYMBOLS[o];return f?`${g}${f}${s}`:`${g}${o} ${s}`};
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,o=t;if(null==o||Number.isNaN(o))return"";if(hasIntlNumber())try{const t={};return null!=n&&(t.minimumFractionDigits=n,t.maximumFractionDigits=n),numberFormat(e??"en-IN",t).format(o)}catch{}return null!=n?o.toFixed(n):String(o)}export function formatPercent(t,r,e,n){if("number"!=typeof r&&void 0===e&&void 0===n)return housePercent(t,r);const o="number"==typeof r?r:0,m=t;if(null==m||Number.isNaN(m))return"";const i=e??1?m:m/100;if(hasIntlNumber())try{return numberFormat(n??"en-IN",{style:"percent",minimumFractionDigits:o,maximumFractionDigits:o}).format(i)}catch{}return`${(100*i).toFixed(o)}%`}export const formatCompactNumber=(t,r="en-IN")=>{if(null==t||Number.isNaN(t))return"";if(hasIntlNumber())try{return numberFormat(r,{notation:"compact",maximumFractionDigits:1}).format(t)}catch{}const e=Math.abs(t),n=t<0?"-":"";return e>=1e7?`${n}${(e/1e7).toFixed(1)}Cr`:e>=1e5?`${n}${(e/1e5).toFixed(1)}L`:e>=1e3?`${n}${(e/1e3).toFixed(1)}K`:`${t}`};
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:"",GRAY:"",BLUE:"",YELLOW:"",RED_BOLD:""},LogLevels={DEBUG:{level:"debug",color:Colors.GRAY},INFO:{level:"info",color:Colors.BLUE},WARN:{level:"warn",color:Colors.YELLOW},ERROR:{level:"error",color:Colors.RED_BOLD}},isLogLevelAllowed=e=>{const r=["debug","info","warn","error"],o=getConfigValue("logLevel","info");return r.indexOf(e)>=r.indexOf(o)},isEnabled=()=>getConfigValue("loggingEnabled",!0);let remote=null;export const setRemoteLogger=e=>{remote=e};const safe=e=>{if(e)try{e()}catch{}},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:s}=shouldForward(o);t&&safe(()=>remote?.recordError?.(e,buildErrorContext(r,s)))},logDebug=(e,...r)=>{isEnabled()&&isLogLevelAllowed(LogLevels.DEBUG.level)&&console.debug(`${LogLevels.DEBUG.color}[DEBUG]: ${redactString(e)}${Colors.RESET}`,...redact(r))},logInfo=(e,...r)=>{const o=redactString(e),t=redact(r);isEnabled()&&isLogLevelAllowed(LogLevels.INFO.level)&&(console.info(`${LogLevels.INFO.color}[INFO]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("info",o,t)))},logWarning=(e,...r)=>{const o=redactString(e),t=redact(r);isEnabled()&&isLogLevelAllowed(LogLevels.WARN.level)&&(console.warn(`${LogLevels.WARN.color}[WARNING]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("warn",o,t)))},logError=(e,...r)=>{const o=redactString(e),t=redact(r);isEnabled()&&isLogLevelAllowed(LogLevels.ERROR.level)&&console.error(`${LogLevels.ERROR.color}[ERROR]: ${o}${Colors.RESET}`,...t),safe(()=>remote?.log?.("error",o,t));const s=t[0];void 0===s||isNoResponse(r[0])||forwardErrorToRemote(toErrorObject(s),{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=[],...s}=r,n=asDict(e),l=asDict(n?.config),i=asDict(n?.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"===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(isNoResponse(e))return void logInfo(`${u} got no response`);if(null!==d&&t.includes(d))return void logInfo(`${u} refused (${d})`);const f="string"==typeof n?.message?n.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,...s});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
+ "use strict";import{getConfigValue}from"../config/index.js";import{isNoResponse}from"../errors/extractApiError.js";import{redact,redactString}from"./redact.js";const Colors={RESET:"",GRAY:"",BLUE:"",YELLOW:"",RED_BOLD:""},LogLevels={DEBUG:{level:"debug",color:Colors.GRAY},INFO:{level:"info",color:Colors.BLUE},WARN:{level:"warn",color:Colors.YELLOW},ERROR:{level:"error",color:Colors.RED_BOLD}},isLogLevelAllowed=e=>{const r=["debug","info","warn","error"],o=getConfigValue("logLevel","info");return r.indexOf(e)>=r.indexOf(o)},isEnabled=()=>getConfigValue("loggingEnabled",!0);let remote=null;export const setRemoteLogger=e=>{remote=e};const safe=e=>{if(e)try{e()}catch{}},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":"denied":"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"granted"===t||"limited"===t||"blocked"===t||"unavailable"===t?t:requestPermission(e)},openSettings:openAppSettings};
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};
@@ -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":"unknown",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
+ "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 or empty placeholder for the whole app. Call it
36
- * once at startup; a key left out (or undefined) keeps its current value.
37
- * Passing nothing restores the defaults (IST, en-IN, "-", house text).
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") always shows as that day;
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
- export type PermissionStatus = 'unavailable' | 'denied' | 'limited' | 'granted' | 'blocked';
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 if not yet granted. */
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
- * (`unknown` when the person has not been asked yet, `denied` when refused).
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
- /** The push permission values, as runtime constants an app can compare against. */
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 or empty placeholder for the whole app. Call it
36
- * once at startup; a key left out (or undefined) keeps its current value.
37
- * Passing nothing restores the defaults (IST, en-IN, "-", house text).
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") always shows as that day;
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
- export type PermissionStatus = 'unavailable' | 'denied' | 'limited' | 'granted' | 'blocked';
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 if not yet granted. */
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
- * (`unknown` when the person has not been asked yet, `denied` when refused).
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
- /** The push permission values, as runtime constants an app can compare against. */
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.10.0",
3
+ "version": "0.11.1",
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",