@webority/web-core 0.76.0 → 0.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,7 +16,7 @@ store.
16
16
  | `api` | `publicClient`, `userClient`, `initUserAuth`, single-flight token refresh, a cross-tab refresh lock, retry of safe requests, the client headers and the minimum-version header reader |
17
17
  | `auth` | the token store (`getToken`, `storeToken`, `removeToken`), the synchronous `hasSession`, the session user, `clearSession` and `addSessionEndedListener`, `hasSessionEndedInTab`, JWT helpers, "keep me signed in" |
18
18
  | `config` | `setConfig`, `getConfig`, `getConfigValue`: base URL, version, commit, build number, log settings, request timeout, retry count, correlation-id header |
19
- | `errors` | `extractApiError`: any thrown value to `{ code, message, fieldErrors, status, offline }`, with `code` `'timeout'` or `'network'` when no answer arrived; `apiErrorMessage(error, fallback)`; `isNoResponse` |
19
+ | `errors` | `extractApiError`: any thrown value to `{ code, message, fieldErrors, status, offline }`, with `code` `'network'`, `'timeout'` or `'offline'` when no answer arrived (`offline` is true for all three, and `'offline'` only when the browser reports no network); `apiErrorMessage(error, fallback)`; `isNoResponse` |
20
20
  | `formatters` | house date, time, number, percent and money (`formatMinor`) formatters; India Standard Time by default, the viewer's zone on request |
21
21
  | `logger` | levelled `Logger` with secret redaction, and `Logger.requestFailed` for a failed service call |
22
22
  | `network` | `useNetworkStatus` and the online/offline listener |
@@ -173,11 +173,12 @@ try {
173
173
  `extractApiError` reads `errors` as a ModelState dictionary or as a list of `{ field, message }`
174
174
  entries, both into `fieldErrors` keyed by the camelCase field path. For the sentence a screen shows,
175
175
  `apiErrorMessage(error, "We couldn't save the project.")` returns the server's curated message, or
176
- the screen's fallback when the server said nothing usable (a 5xx, an empty body), or the connection
177
- message when no answer arrived. `apiErrorMessage(error, null)` says nothing (returns `null`) when the
176
+ the screen's fallback when the server said nothing usable (a 5xx without a curated message, an empty
177
+ body), or the connection message when no answer arrived, which wins over the fallback. A 5xx whose
178
+ body has a code other than `internal_error` and a curated message shows that message. `apiErrorMessage(error, null)` says nothing (returns `null`) when the
178
179
  server sent nothing curated, for a panel that shows only the server's own sentence. `isNoResponse(error)`
179
180
  says whether an answer arrived at all; `code` tells a timeout (`TIMEOUT_CODE`) from a network failure
180
- (`NETWORK_CODE`).
181
+ while online (`NETWORK_CODE`) and from a browser that reports no network (`OFFLINE_CODE`).
181
182
 
182
183
  Errors raise a toast by default; a thunk or endpoint opts out with `meta: { silent: true }`, the
183
184
  same on web and mobile. `onRejected` gives the product its say over each rejection before the
@@ -1,2 +1,2 @@
1
- var e=`Something went wrong on our side. Please try again in a moment.`,t=`You appear to be offline. Check your connection and try again.`,n=`That took too long to respond. Check your connection and try again.`,r=`Something went wrong. Please try again.`,i=`request_canceled`,a=`contract_error`,o=`timeout`,s=`network`,c=e=>`Request failed (${e})`,l=e=>typeof e==`object`&&!!e&&!Array.isArray(e),u=e=>typeof e==`string`&&e.trim().length>0?e:null,d=e=>e.length>300||/^\s*</.test(e)||e.includes(`
2
- at `)||/\b(Exception|StackTrace):/.test(e)||/\b(System|Microsoft)\.[A-Za-z]+\.[A-Za-z]/.test(e),f=e=>{let t=u(e);return t!==null&&!d(t)?t:null},p=e=>e.replace(/^\$\.?/,``).split(`.`).map(e=>e.charAt(0).toLowerCase()+e.slice(1)).join(`.`),m=e=>{if(Array.isArray(e)){for(let t of e){let e=u(t);if(e!==null)return e}return null}return u(e)},h=(e,t,n)=>{let r=p(t);r===``?e.form??=n:r in e.fields||(e.fields[r]=n)},g=e=>{let t={fields:{},form:null};if(Array.isArray(e)){for(let n of e){if(!l(n))continue;let e=u(n.message);e!==null&&h(t,typeof n.field==`string`?n.field:``,e)}return t}if(!l(e))return t;for(let[n,r]of Object.entries(e)){let e=m(r);e!==null&&h(t,n,e)}return t},_=e=>{let t=e.error;return l(t)?u(t.message):u(t)},v=e=>l(e)&&typeof e.message==`string`&&typeof e.status==`number`&&typeof e.offline==`boolean`&&l(e.fieldErrors),y=e=>({code:null,fieldErrors:{},status:0,offline:!1,traceId:null,detail:null,...e}),b=e=>{let a=u(e.code),c=u(e.name),l=u(e.message);return y(c===`CanceledError`||a===`ERR_CANCELED`?{code:i,message:r,detail:l}:a===`ECONNABORTED`||a===`ETIMEDOUT`?{code:o,message:n,offline:!0,detail:l}:c===`RequestOfflineError`||a===`ERR_NETWORK`||l===`Network Error`?{code:s,message:t,offline:!0,detail:l}:{message:r,detail:l})};function x(t){if(v(t))return t;if(typeof t==`string`)return y({message:f(t)??`Something went wrong. Please try again.`,detail:t||null});if(!l(t))return y({message:r,detail:t==null?null:String(t)});if(t.isContractError===!0)return y({code:a,message:f(t.message)??`Something went wrong. Please try again.`,detail:u(t.message)});let n=l(t.response)?t.response:null,i=typeof n?.status==`number`?n.status:typeof t.status==`number`?t.status:0,o=n?n.data:t.body;if(i===0&&o==null)return b(t);let s=l(o)?o:null,{fields:d,form:p}=g(s?.errors),m=u(s?.code),h=u(s?.traceId),x=u(s?.message)??u(s?.detail)??(s?_(s):null)??u(s?.title)??u(o)??u(t.message),S;return S=i>=500?e:f(Object.values(d)[0])??f(p)??f(s?.message)??f(s?.detail)??(s?f(_(s)):null)??f(s?.title)??f(o)??(i?c(i):`Something went wrong. Please try again.`),y({code:m,message:S,fieldErrors:d,status:i,traceId:h,detail:x})}var S=e=>x(e).offline;function C(e,t){let n=x(e);return n.offline||t!==null&&!t?n.message:n.status>=500||n.code===`request_canceled`||n.message===`Something went wrong. Please try again.`||n.message===c(n.status)?t??null:n.message}export{a as CONTRACT_ERROR_CODE,s as NETWORK_CODE,t as OFFLINE_MESSAGE,i as REQUEST_CANCELED_CODE,e as SERVER_FAILURE_MESSAGE,o as TIMEOUT_CODE,n as TIMEOUT_MESSAGE,r as UNEXPECTED_MESSAGE,C as apiErrorMessage,x as extractApiError,v as isApiError,S as isNoResponse,p as toFieldPath};
1
+ var e=`Something went wrong on our side. Please try again in a moment.`,t=`You appear to be offline. Check your connection and try again.`,n=`We couldn't reach the server. Check your connection and try again.`,r=`That took too long to respond. Check your connection and try again.`,i=`Something went wrong. Please try again.`,a=`request_canceled`,o=`contract_error`,s=`timeout`,c=`network`,l=`offline`,u=e=>`Request failed (${e})`,d=e=>typeof e==`object`&&!!e&&!Array.isArray(e),f=e=>typeof e==`string`&&e.trim().length>0?e:null,p=e=>e.length>300||/^\s*</.test(e)||e.includes(`
2
+ at `)||/\b(Exception|StackTrace):/.test(e)||/\b(System|Microsoft)\.[A-Za-z]+\.[A-Za-z]/.test(e),m=e=>{let t=f(e);return t!==null&&!p(t)?t:null},h=e=>e.replace(/^\$\.?/,``).split(`.`).map(e=>e.charAt(0).toLowerCase()+e.slice(1)).join(`.`),g=e=>{if(Array.isArray(e)){for(let t of e){let e=f(t);if(e!==null)return e}return null}return f(e)},_=(e,t,n)=>{let r=h(t);r===``?e.form??=n:r in e.fields||(e.fields[r]=n)},v=e=>{let t={fields:{},form:null};if(Array.isArray(e)){for(let n of e){if(!d(n))continue;let e=f(n.message);e!==null&&_(t,typeof n.field==`string`?n.field:``,e)}return t}if(!d(e))return t;for(let[n,r]of Object.entries(e)){let e=g(r);e!==null&&_(t,n,e)}return t},y=e=>{let t=e.error;return d(t)?f(t.message):f(t)},b=e=>d(e)&&typeof e.message==`string`&&typeof e.status==`number`&&typeof e.offline==`boolean`&&d(e.fieldErrors),x=e=>({code:null,fieldErrors:{},status:0,offline:!1,traceId:null,detail:null,...e}),S=()=>typeof navigator<`u`&&navigator.onLine===!1,C=e=>{let o=f(e.code),u=f(e.name),d=f(e.message);return u===`CanceledError`||o===`ERR_CANCELED`?x({code:a,message:i,detail:d}):o===`ECONNABORTED`||o===`ETIMEDOUT`?x({code:s,message:r,offline:!0,detail:d}):u===`RequestOfflineError`||o===`ERR_NETWORK`||d===`Network Error`?S()?x({code:l,message:t,offline:!0,detail:d}):x({code:c,message:n,offline:!0,detail:d}):x({message:i,detail:d})};function w(e){if(b(e))return e;if(typeof e==`string`)return x({message:m(e)??`Something went wrong. Please try again.`,detail:e||null});if(!d(e))return x({message:i,detail:e==null?null:String(e)});if(e.isContractError===!0)return x({code:o,message:m(e.message)??`Something went wrong. Please try again.`,detail:f(e.message)});let t=d(e.response)?e.response:null,n=typeof t?.status==`number`?t.status:typeof e.status==`number`?e.status:0,r=t?t.data:e.body;if(n===0&&r==null)return C(e);let a=d(r)?r:null,{fields:s,form:c}=v(a?.errors),l=f(a?.code),p=f(a?.traceId),h=f(a?.message)??f(a?.detail)??(a?y(a):null)??f(a?.title)??f(r)??f(e.message),g;return g=n>=500?(l!==null&&l!==`internal_error`?m(a?.message):null)??`Something went wrong on our side. Please try again in a moment.`:m(Object.values(s)[0])??m(c)??m(a?.message)??m(a?.detail)??(a?m(y(a)):null)??m(a?.title)??m(r)??(n?u(n):`Something went wrong. Please try again.`),x({code:l,message:g,fieldErrors:s,status:n,traceId:p,detail:h})}var T=e=>w(e).offline;function E(e,t){let n=w(e);return n.offline||t!==null&&!t||n.status>=500&&n.message!==`Something went wrong on our side. Please try again in a moment.`?n.message:n.status>=500||n.code===`request_canceled`||n.message===`Something went wrong. Please try again.`||n.message===u(n.status)?t??null:n.message}export{o as CONTRACT_ERROR_CODE,c as NETWORK_CODE,l as OFFLINE_CODE,t as OFFLINE_MESSAGE,a as REQUEST_CANCELED_CODE,e as SERVER_FAILURE_MESSAGE,s as TIMEOUT_CODE,r as TIMEOUT_MESSAGE,i as UNEXPECTED_MESSAGE,n as UNREACHABLE_MESSAGE,E as apiErrorMessage,w as extractApiError,b as isApiError,T as isNoResponse,h as toFieldPath};
@@ -1 +1 @@
1
- import{CONTRACT_ERROR_CODE as e,NETWORK_CODE as t,OFFLINE_MESSAGE as n,REQUEST_CANCELED_CODE as r,SERVER_FAILURE_MESSAGE as i,TIMEOUT_CODE as a,TIMEOUT_MESSAGE as o,UNEXPECTED_MESSAGE as s,apiErrorMessage as c,extractApiError as l,isApiError as u,isNoResponse as d,toFieldPath as f}from"./extractApiError.js";export{e as CONTRACT_ERROR_CODE,t as NETWORK_CODE,n as OFFLINE_MESSAGE,r as REQUEST_CANCELED_CODE,i as SERVER_FAILURE_MESSAGE,a as TIMEOUT_CODE,o as TIMEOUT_MESSAGE,s as UNEXPECTED_MESSAGE,c as apiErrorMessage,l as extractApiError,u as isApiError,d as isNoResponse,f as toFieldPath};
1
+ import{CONTRACT_ERROR_CODE as e,NETWORK_CODE as t,OFFLINE_CODE as n,OFFLINE_MESSAGE as r,REQUEST_CANCELED_CODE as i,SERVER_FAILURE_MESSAGE as a,TIMEOUT_CODE as o,TIMEOUT_MESSAGE as s,UNEXPECTED_MESSAGE as c,UNREACHABLE_MESSAGE as l,apiErrorMessage as u,extractApiError as d,isApiError as f,isNoResponse as p,toFieldPath as m}from"./extractApiError.js";export{e as CONTRACT_ERROR_CODE,t as NETWORK_CODE,n as OFFLINE_CODE,r as OFFLINE_MESSAGE,i as REQUEST_CANCELED_CODE,a as SERVER_FAILURE_MESSAGE,o as TIMEOUT_CODE,s as TIMEOUT_MESSAGE,c as UNEXPECTED_MESSAGE,l as UNREACHABLE_MESSAGE,u as apiErrorMessage,d as extractApiError,f as isApiError,p as isNoResponse,m as toFieldPath};
@@ -1 +1 @@
1
- import{configuredLocale as e,getFormatterConfig as t,isFormatterConfigured as n,numberSeparators as r,styledNumber as i}from"./formatConfig.js";import{numberFormat as a}from"./intlCache.js";var o=()=>typeof Intl<`u`&&typeof Intl.NumberFormat==`function`,s=(e,t)=>{let{decimal:n,group:i}=r()??{decimal:`.`,group:`,`},a=e<0?`-`:``,[o,s]=Math.abs(e).toFixed(t).split(`.`),c=o.length>3?o.slice(-3):o,l=o.length>3?o.slice(0,-3):``;return a+(l?l.replace(/\B(?=(\d{2})+(?!\d))/g,i)+i+c:c)+(s?`${n}${s}`:``)},c=e=>{if(e==null||typeof e==`string`&&e.trim()===``)return null;let t=typeof e==`number`?e:Number(e);return Number.isFinite(t)?t:null},l=(e,t)=>a(e,{style:`currency`,currency:t}).resolvedOptions().maximumFractionDigits??2,u=(r,u={})=>{let{currency:d=`INR`,locale:f=e()??`en-IN`,minimumFractionDigits:p,maximumFractionDigits:m,stripSymbol:h=!1,empty:g=n(`locale`)||n(`empty`)?t().empty:``,..._}=u,v=c(r);if(v===null)return g;if(o())try{let e=m??l(f,d),t=p??(Number.isInteger(v)?0:e),n=i(a(f,{..._,style:`currency`,currency:d,minimumFractionDigits:t,maximumFractionDigits:Math.max(t,e)}),v);return h?n.replace(/[^\d,.\s\-+]/g,``).trim():n}catch{}let y=s(v,p??(Number.isInteger(v)?0:2));return h?y:d===`INR`?`₹${y}`:`${d} ${y}`};export{u as formatCurrency};
1
+ import{devWarn as e}from"../lib/devWarn.js";import{configuredLocale as t,getFormatterConfig as n,isFormatterConfigured as r,numberSeparators as i,styledNumber as a}from"./formatConfig.js";import{numberFormat as o}from"./intlCache.js";var s=()=>typeof Intl<`u`&&typeof Intl.NumberFormat==`function`,c=(e,t)=>{let{decimal:n,group:r}=i()??{decimal:`.`,group:`,`},a=e<0?`-`:``,[o,s]=Math.abs(e).toFixed(t).split(`.`),c=o.length>3?o.slice(-3):o,l=o.length>3?o.slice(0,-3):``;return a+(l?l.replace(/\B(?=(\d{2})+(?!\d))/g,r)+r+c:c)+(s?`${n}${s}`:``)},l=e=>{if(e==null||typeof e==`string`&&e.trim()===``)return null;let t=typeof e==`number`?e:Number(e);return Number.isFinite(t)?t:null},u=(e,t)=>o(e,{style:`currency`,currency:t}).resolvedOptions().maximumFractionDigits??2,d=(i,d={})=>{let{currency:f,locale:p=t()??`en-IN`,minimumFractionDigits:m,maximumFractionDigits:h,stripSymbol:g=!1,empty:_=r(`locale`)||r(`empty`)?n().empty:``,...v}=d;f||e(`[@webority/web-core] formatCurrency called without options.currency: it prints INR for now and throws from 0.78.0. Pass an ISO 4217 code.`);let y=f||`INR`,b=l(i);if(b===null)return _;if(s())try{let e=h??u(p,y),t=m??(Number.isInteger(b)?0:e),n=a(o(p,{...v,style:`currency`,currency:y,minimumFractionDigits:t,maximumFractionDigits:Math.max(t,e)}),b);return g?n.replace(/[^\d,.\s\-+]/g,``).trim():n}catch{}let x=c(b,m??(Number.isInteger(b)?0:2));return g?x:y===`INR`?`₹${x}`:`${y} ${x}`};export{d as formatCurrency};
@@ -1 +1 @@
1
- import{configuredLocale as e,getFormatterConfig as t,groupingForLocale as n,numberSeparators as r,styledNumber as i}from"./formatConfig.js";import{dateTimeFormat as a,numberFormat as o,relativeTimeFormat as s}from"./intlCache.js";var c=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],l=330,u=[`IST`,`Asia/Kolkata`,`Asia/Calcutta`],d=/^\d{4}-\d{2}-\d{2}$/,f=e=>e<10?`0${e}`:`${e}`,p=e=>e??t().empty,m=e=>{if(e==null||e===``)return null;let t=e instanceof Date?e:new Date(typeof e==`string`?e.trim():e);return Number.isNaN(t.getTime())?null:t},h=e=>typeof e==`string`&&d.test(e.trim()),g=e=>{if(e===0)return`GMT`;let t=e>0?`+`:`-`,n=Math.abs(e),r=n%60;return`GMT${t}${Math.floor(n/60)}${r===0?``:`:${f(r)}`}`},_=(e,t,n)=>{let r=new Date(e.getTime()+t*6e4);return{year:r.getUTCFullYear(),month:r.getUTCMonth(),day:r.getUTCDate(),hour:r.getUTCHours(),minute:r.getUTCMinutes(),label:n}},v=(e,t)=>{let n=a(`en-US`,{timeZone:t,year:`numeric`,month:`numeric`,day:`numeric`,hour:`numeric`,minute:`numeric`,hour12:!1}).formatToParts(e),r=e=>Number.parseInt(n.find(t=>t.type===e)?.value??``,10),i=r(`year`),o=r(`month`)-1,s=r(`day`),c=r(`hour`)%24,l=r(`minute`);return{year:i,month:o,day:s,hour:c,minute:l,label:g(Math.round((Date.UTC(i,o,s,c,l)-Math.floor(e.getTime()/6e4)*6e4)/6e4))}},y=(e,t)=>u.includes(t)?_(e,l,`IST`):t===`UTC`?_(e,0,`UTC`):t===`viewer`?{year:e.getFullYear(),month:e.getMonth(),day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),label:g(-e.getTimezoneOffset())}:v(e,t),b=e=>e.hourCycle??12,x=e=>`${f(e.day)}-${c[e.month]}-${e.year}`,S=(e,t)=>{let n=f(e.day),r=f(e.month+1),i=String(e.year).padStart(4,`0`);return t===`DayMonthYear`?`${n}/${r}/${i}`:t===`MonthDayYear`?`${r}/${n}/${i}`:`${i}-${r}-${n}`},C=(e,t)=>t===24?`${f(e.hour)}:${f(e.minute)}`:`${e.hour%12||12}:${f(e.minute)} ${e.hour<12?`AM`:`PM`}`,w=(e,t)=>t??!u.includes(e),T=(e,t,n,r)=>w(n,r)?`${e} ${t.label}`:e,E=e=>{if(e!==`viewer`)return u.includes(e)?`Asia/Kolkata`:e},D=(e,t,n)=>{let r=a(t,{day:`2-digit`,month:`short`,year:`numeric`,timeZone:n}).formatToParts(e),i=e=>r.find(t=>t.type===e)?.value??``;return`${i(`day`)}-${i(`month`).replace(`.`,``)}-${i(`year`)}`},O=(n,r)=>{let i=t().dateOrder??`DayMonthNameYear`;if(i!==`DayMonthNameYear`)return S(y(n,r),i);let a=e();return a?D(n,a,E(r)):x(y(n,r))},k=(e,t,n,r)=>a(t,{hour:`2-digit`,minute:`2-digit`,timeZone:E(n),timeZoneName:w(n,r.zoneLabel)?`short`:void 0,hourCycle:r.hourCycle===void 0?void 0:r.hourCycle===24?`h23`:`h12`}).format(e),A=(e,n={})=>{let r=m(e);return r?O(r,h(e)?`UTC`:n.zone??t().zone):p(n.empty)},ee=(n,r={})=>{let i=m(n);if(!i)return p(r.empty);let a=r.zone??t().zone,o=e();if(o)return k(i,o,a,r);let s=y(i,a);return T(C(s,b(r)),s,a,r.zoneLabel)},te=(n,r={})=>{let i=m(n);if(!i)return p(r.empty);let a=r.zone??t().zone,o=e();if(o)return`${O(i,a)}, ${k(i,o,a,r)}`;let s=y(i,a);return T(`${O(i,a)}, ${C(s,b(r))}`,s,a,r.zoneLabel)},j=1e3,M=60*j,N=60*M,P=24*N,F=7*P,I=30*P,L=365*P,R=[[`year`,L],[`month`,I],[`day`,P],[`hour`,N],[`minute`,M]],z=(n,r={})=>{let i=m(n),a=m(r.now??Date.now());if(!i||!a)return p(r.empty);let o=i.getTime()-a.getTime(),c=Math.abs(o),l=Intl.RelativeTimeFormat,u=e();if((u!==null||r.intl===!0)&&typeof l==`function`){let e=s(l,u??t().locale),[n,r]=R.find(([,e])=>c>=e)??[`second`,j];return e.format(Math.round(o/r),n)}if(c<M)return`just now`;let[d,f]=c<N?[`minute`,M]:c<P?[`hour`,N]:c<F?[`day`,P]:c<I?[`week`,F]:c<L?[`month`,I]:[`year`,L],h=Math.floor(c/f),g=`${h} ${d}${h===1?``:`s`}`;return o<0?`${g} ago`:`in ${g}`},B=e=>{if(e==null||typeof e==`string`&&e.trim()===``)return null;let t=typeof e==`number`?e:Number(e);return Number.isFinite(t)?t:null},V=e=>Math.min(20,Math.max(0,Math.trunc(e))),H=(e,t)=>/e/i.test(String(e))?e*10**t:Number(`${e}e${t}`),U=()=>r()??{decimal:`.`,group:`,`},W=(e,t,n)=>t===`none`||e.length<=3?e:t===`international`?e.replace(/\B(?=(\d{3})+(?!\d))/g,n):`${e.slice(0,-3).replace(/\B(?=(\d{2})+(?!\d))/g,n)}${n}${e.slice(-3)}`,G=()=>typeof Intl<`u`&&typeof Intl.NumberFormat==`function`,K=(e,t)=>{if(G())return o(`en-US`,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t}).format(e);let n=Math.min(t,15);return H(Math.round(H(e,n)),-n).toFixed(n)},q=(e,t,n,r)=>{let i=Math.max(V(n),V(t)),a=V(t),o=K(Math.abs(e),i),[s=`0`,c=``]=o.split(`.`),l=c.padEnd(a,`0`);for(;l.length>a&&l.endsWith(`0`);)l=l.slice(0,-1);let u=U(),d=W(s,r,u.group)+(l?`${u.decimal}${l}`:``);return e<0&&/[1-9]/.test(o)?`-${d}`:d},J=new Set([`grouping`,`minimumFractionDigits`,`maximumFractionDigits`,`locale`,`empty`,`scale`]),Y=e=>{if(!Object.entries(e).some(([e,t])=>t!==void 0&&!J.has(e)))return null;let{grouping:t,locale:n,empty:r,scale:i,...a}=e;return t===`none`&&a.useGrouping===void 0?{...a,useGrouping:!1}:a},X=e=>e.locale??t().locale,Z=t=>{let n=e();return n===null||t.grouping===`indian`||t.grouping===`international`?null:t.locale??n},Q=(e,t)=>{let n=V(e);return{minimumFractionDigits:n,maximumFractionDigits:Math.max(n,V(t))}},$=e=>e===`none`?{useGrouping:!1}:{},ne=(e,t={})=>{let r=B(e);if(r===null)return p(t.empty);let a=Y(t);if(a)return i(o(X(t),a),r);let s=Z(t);return s?i(o(s,{...Q(t.minimumFractionDigits??0,t.maximumFractionDigits??3),...$(t.grouping)}),r):q(r,t.minimumFractionDigits??0,t.maximumFractionDigits??3,t.grouping??n(X(t)))},re=(e,t={})=>{let r=B(e);if(r===null)return p(t.empty);let a=Y(t);if(a){let e=t.scale===`percent`?H(r,-2):r;return i(o(X(t),{style:`percent`,...a}),e)}let s=Z(t);if(s){let e=t.scale===`percent`?H(r,-2):r;return i(o(s,{style:`percent`,...Q(t.minimumFractionDigits??0,t.maximumFractionDigits??t.minimumFractionDigits??0),...$(t.grouping)}),e)}return`${q(t.scale===`percent`?r:H(r,2),t.minimumFractionDigits??0,t.maximumFractionDigits??t.minimumFractionDigits??0,t.grouping??n(X(t)))}%`},ie={INR:`₹`,USD:`$`,EUR:`€`,GBP:`£`},ae={JPY:0,KRW:0,VND:0,BHD:3,JOD:3,KWD:3,OMR:3,TND:3},oe=(e,t={})=>{let n=B(e);if(n===null)return p(t.empty);let r=(t.currency??`INR`).toUpperCase(),a=ae[r]??2,s=Math.round(Math.abs(n)),c=String(s).padStart(a+1,`0`),l=c.slice(0,c.length-a),u=c.slice(c.length-a);t.dropZeroDecimals&&/^0*$/.test(u)&&(u=``);let d=Z({grouping:t.grouping});if(d)try{let e=Number(`${n<0&&s!==0?`-`:``}${l}.${c.slice(c.length-a)||`0`}`);return i(o(d,{...t.symbol===!1?{}:{style:`currency`,currency:r},...Q(u?a:0,a),...$(t.grouping)}),e)}catch{}let f=t.grouping??(r===`INR`?`indian`:`international`),m=U(),h=W(l,f,m.group)+(u?`${m.decimal}${u}`:``),g=n<0&&s!==0?`-`:``;if(t.symbol===!1)return`${g}${h}`;let _=ie[r];return _?`${g}${_}${h}`:`${g}${r} ${h}`};export{A as formatDate,te as formatDateTime,oe as formatMinor,ne as formatNumber,re as formatPercent,z as formatRelative,ee as formatTime};
1
+ import{devWarn as e}from"../lib/devWarn.js";import{configuredLocale as t,getFormatterConfig as n,groupingForLocale as r,numberSeparators as i,styledNumber as a}from"./formatConfig.js";import{dateTimeFormat as o,numberFormat as s,relativeTimeFormat as c}from"./intlCache.js";var l=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],u=330,d=[`IST`,`Asia/Kolkata`,`Asia/Calcutta`],f=/^\d{4}-\d{2}-\d{2}$/,p=e=>e<10?`0${e}`:`${e}`,m=e=>e??n().empty,h=e=>{if(e==null||e===``)return null;let t=e instanceof Date?e:new Date(typeof e==`string`?e.trim():e);return Number.isNaN(t.getTime())?null:t},g=e=>typeof e==`string`&&f.test(e.trim()),_=e=>{if(e===0)return`GMT`;let t=e>0?`+`:`-`,n=Math.abs(e),r=n%60;return`GMT${t}${Math.floor(n/60)}${r===0?``:`:${p(r)}`}`},v=(e,t,n)=>{let r=new Date(e.getTime()+t*6e4);return{year:r.getUTCFullYear(),month:r.getUTCMonth(),day:r.getUTCDate(),hour:r.getUTCHours(),minute:r.getUTCMinutes(),label:n}},ee=(e,t)=>{let n=o(`en-US`,{timeZone:t,year:`numeric`,month:`numeric`,day:`numeric`,hour:`numeric`,minute:`numeric`,hour12:!1}).formatToParts(e),r=e=>Number.parseInt(n.find(t=>t.type===e)?.value??``,10),i=r(`year`),a=r(`month`)-1,s=r(`day`),c=r(`hour`)%24,l=r(`minute`);return{year:i,month:a,day:s,hour:c,minute:l,label:_(Math.round((Date.UTC(i,a,s,c,l)-Math.floor(e.getTime()/6e4)*6e4)/6e4))}},y=(e,t)=>d.includes(t)?v(e,u,`IST`):t===`UTC`?v(e,0,`UTC`):t===`viewer`?{year:e.getFullYear(),month:e.getMonth(),day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),label:_(-e.getTimezoneOffset())}:ee(e,t),b=e=>e.hourCycle??12,te=e=>`${p(e.day)}-${l[e.month]}-${e.year}`,x=(e,t)=>{let n=p(e.day),r=p(e.month+1),i=String(e.year).padStart(4,`0`);return t===`DayMonthYear`?`${n}/${r}/${i}`:t===`MonthDayYear`?`${r}/${n}/${i}`:`${i}-${r}-${n}`},S=(e,t)=>t===24?`${p(e.hour)}:${p(e.minute)}`:`${e.hour%12||12}:${p(e.minute)} ${e.hour<12?`AM`:`PM`}`,C=(e,t)=>t??!d.includes(e),w=(e,t,n,r)=>C(n,r)?`${e} ${t.label}`:e,T=e=>{if(e!==`viewer`)return d.includes(e)?`Asia/Kolkata`:e},ne=(e,t,n)=>{let r=o(t,{day:`2-digit`,month:`short`,year:`numeric`,timeZone:n}).formatToParts(e),i=e=>r.find(t=>t.type===e)?.value??``;return`${i(`day`)}-${i(`month`).replace(`.`,``)}-${i(`year`)}`},E=(e,r)=>{let i=n().dateOrder??`DayMonthNameYear`;if(i!==`DayMonthNameYear`)return x(y(e,r),i);let a=t();return a?ne(e,a,T(r)):te(y(e,r))},D=(e,t,n,r)=>o(t,{hour:`2-digit`,minute:`2-digit`,timeZone:T(n),timeZoneName:C(n,r.zoneLabel)?`short`:void 0,hourCycle:r.hourCycle===void 0?void 0:r.hourCycle===24?`h23`:`h12`}).format(e),O=(e,t={})=>{let r=h(e);return r?E(r,g(e)?`UTC`:t.zone??n().zone):m(t.empty)},k=(e,r={})=>{let i=h(e);if(!i)return m(r.empty);let a=r.zone??n().zone,o=t();if(o)return D(i,o,a,r);let s=y(i,a);return w(S(s,b(r)),s,a,r.zoneLabel)},A=(e,r={})=>{let i=h(e);if(!i)return m(r.empty);let a=r.zone??n().zone,o=t();if(o)return`${E(i,a)}, ${D(i,o,a,r)}`;let s=y(i,a);return w(`${E(i,a)}, ${S(s,b(r))}`,s,a,r.zoneLabel)},j=1e3,M=60*j,N=60*M,P=24*N,F=7*P,I=30*P,L=365*P,R=[[`year`,L],[`month`,I],[`day`,P],[`hour`,N],[`minute`,M]],z=(e,r={})=>{let i=h(e),a=h(r.now??Date.now());if(!i||!a)return m(r.empty);let o=i.getTime()-a.getTime(),s=Math.abs(o),l=Intl.RelativeTimeFormat,u=t();if((u!==null||r.intl===!0)&&typeof l==`function`){let e=c(l,u??n().locale),[t,r]=R.find(([,e])=>s>=e)??[`second`,j];return e.format(Math.round(o/r),t)}if(s<M)return`just now`;let[d,f]=s<N?[`minute`,M]:s<P?[`hour`,N]:s<F?[`day`,P]:s<I?[`week`,F]:s<L?[`month`,I]:[`year`,L],p=Math.floor(s/f),g=`${p} ${d}${p===1?``:`s`}`;return o<0?`${g} ago`:`in ${g}`},B=e=>{if(e==null||typeof e==`string`&&e.trim()===``)return null;let t=typeof e==`number`?e:Number(e);return Number.isFinite(t)?t:null},V=e=>Math.min(20,Math.max(0,Math.trunc(e))),H=(e,t)=>/e/i.test(String(e))?e*10**t:Number(`${e}e${t}`),U=()=>i()??{decimal:`.`,group:`,`},W=(e,t,n)=>t===`none`||e.length<=3?e:t===`international`?e.replace(/\B(?=(\d{3})+(?!\d))/g,n):`${e.slice(0,-3).replace(/\B(?=(\d{2})+(?!\d))/g,n)}${n}${e.slice(-3)}`,G=()=>typeof Intl<`u`&&typeof Intl.NumberFormat==`function`,K=(e,t)=>{if(G())return s(`en-US`,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t}).format(e);let n=Math.min(t,15);return H(Math.round(H(e,n)),-n).toFixed(n)},q=(e,t,n,r)=>{let i=Math.max(V(n),V(t)),a=V(t),o=K(Math.abs(e),i),[s=`0`,c=``]=o.split(`.`),l=c.padEnd(a,`0`);for(;l.length>a&&l.endsWith(`0`);)l=l.slice(0,-1);let u=U(),d=W(s,r,u.group)+(l?`${u.decimal}${l}`:``);return e<0&&/[1-9]/.test(o)?`-${d}`:d},J=new Set([`grouping`,`minimumFractionDigits`,`maximumFractionDigits`,`locale`,`empty`,`scale`]),Y=e=>{if(!Object.entries(e).some(([e,t])=>t!==void 0&&!J.has(e)))return null;let{grouping:t,locale:n,empty:r,scale:i,...a}=e;return t===`none`&&a.useGrouping===void 0?{...a,useGrouping:!1}:a},X=e=>e.locale??n().locale,Z=e=>{let n=t();return n===null||e.grouping===`indian`||e.grouping===`international`?null:e.locale??n},Q=(e,t)=>{let n=V(e);return{minimumFractionDigits:n,maximumFractionDigits:Math.max(n,V(t))}},$=e=>e===`none`?{useGrouping:!1}:{},re=(e,t={})=>{let n=B(e);if(n===null)return m(t.empty);let i=Y(t);if(i)return a(s(X(t),i),n);let o=Z(t);return o?a(s(o,{...Q(t.minimumFractionDigits??0,t.maximumFractionDigits??3),...$(t.grouping)}),n):q(n,t.minimumFractionDigits??0,t.maximumFractionDigits??3,t.grouping??r(X(t)))},ie=(e,t={})=>{let n=B(e);if(n===null)return m(t.empty);let i=Y(t);if(i){let e=t.scale===`percent`?H(n,-2):n;return a(s(X(t),{style:`percent`,...i}),e)}let o=Z(t);if(o){let e=t.scale===`percent`?H(n,-2):n;return a(s(o,{style:`percent`,...Q(t.minimumFractionDigits??0,t.maximumFractionDigits??t.minimumFractionDigits??0),...$(t.grouping)}),e)}return`${q(t.scale===`percent`?n:H(n,2),t.minimumFractionDigits??0,t.maximumFractionDigits??t.minimumFractionDigits??0,t.grouping??r(X(t)))}%`},ae={INR:`₹`,USD:`$`,EUR:`€`,GBP:`£`},oe={JPY:0,KRW:0,VND:0,BHD:3,JOD:3,KWD:3,OMR:3,TND:3},se=(t,n={})=>{n.currency||e(`[@webority/web-core] formatMinor called without options.currency: it prints INR for now and throws from 0.78.0. Pass an ISO 4217 code.`);let r=B(t);if(r===null)return m(n.empty);let i=(n.currency||`INR`).toUpperCase(),o=oe[i]??2,c=Math.round(Math.abs(r)),l=String(c).padStart(o+1,`0`),u=l.slice(0,l.length-o),d=l.slice(l.length-o);n.dropZeroDecimals&&/^0*$/.test(d)&&(d=``);let f=Z({grouping:n.grouping});if(f)try{let e=Number(`${r<0&&c!==0?`-`:``}${u}.${l.slice(l.length-o)||`0`}`);return a(s(f,{...n.symbol===!1?{}:{style:`currency`,currency:i},...Q(d?o:0,o),...$(n.grouping)}),e)}catch{}let p=n.grouping??(i===`INR`?`indian`:`international`),h=U(),g=W(u,p,h.group)+(d?`${h.decimal}${d}`:``),_=r<0&&c!==0?`-`:``;if(n.symbol===!1)return`${_}${g}`;let v=ae[i];return v?`${_}${v}${g}`:`${_}${i} ${g}`};export{O as formatDate,A as formatDateTime,se as formatMinor,re as formatNumber,ie as formatPercent,z as formatRelative,k as formatTime};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{DEFAULT_CORRELATION_ID_HEADER as e,DEFAULT_LOG_LEVEL as t,DEFAULT_RETRIES as n,DEFAULT_TIMEOUT_MS as r,getConfig as i,getConfigValue as a,resetConfig as o,setConfig as s}from"./config/index.js";import{Logger as c,configureLogger as l,getDeviceContext as u,setDeviceContext as d,setRemoteLogger as f}from"./logger/logger.js";import{decodeJWT as p,getJWTExpiry as m,isJWTExpired as h}from"./auth/jwt.js";import{ACCESS_TOKEN_KEY as g,LEGACY_REFRESH_TOKEN_LIFETIME_MS as _,REFRESH_TOKEN_KEY as v,SESSION_USER_KEY as y,addSessionEndedListener as b,clearSession as x,getKeepSignedIn as S,getSessionUser as C,getToken as w,hasSession as T,hasSessionEndedInTab as E,removeSessionUser as D,removeToken as O,setKeepSignedIn as k,setLegacyTokenKeys as A,storeSessionUser as j,storeToken as M}from"./auth/authStore.js";import{addNetworkStatusListener as N,getNetworkStatus as P,setNetworkStatusImplementation as F,useNetworkStatus as I}from"./network/networkStatus.js";import{ACCOUNT_ID_HEADER as L,CLIENT_BUILD_HEADER as R,CLIENT_KIND as z,CLIENT_KIND_HEADER as B,getClientBuild as V}from"./api/clientHeaders.js";import{MIN_APP_VERSION_HEADER as H,addMinAppVersionListener as U,getMinAppVersion as W}from"./api/minAppVersion.js";import{applyRequestDefaults as G,newCorrelationId as K}from"./api/requestDefaults.js";import{WORKSPACE_CHANGED_CODE as q,WorkspaceChangedError as J,isWorkspaceChangedError as Y}from"./api/workspaceChanged.js";import{IDEMPOTENCY_KEY_HEADER as X,attachRetry as Z,isNeverSentError as Q,isRetryableFailure as $,isRetryableStatus as ee,retryAfterMs as te}from"./api/retry.js";import{REFRESH_LOCK_NAME as ne,withCrossTabRefreshLock as re}from"./api/crossTabRefreshLock.js";import ie from"./api/publicClient.js";import{SIGN_OUT_REASON_HEADER as ae,injectStore as oe,injectUserAuth as se,refreshAccessToken as ce,resetRefreshState as le}from"./api/tokenRefresh.js";import ue,{RequestOfflineError as de,SESSION_TERMINATION_CODES as fe}from"./api/userClient.js";import{initUserAuth as pe}from"./initUserAuth.js";import{CONTRACT_ERROR_CODE as me,NETWORK_CODE as he,OFFLINE_MESSAGE as ge,REQUEST_CANCELED_CODE as _e,SERVER_FAILURE_MESSAGE as ve,TIMEOUT_CODE as ye,TIMEOUT_MESSAGE as be,UNEXPECTED_MESSAGE as xe,apiErrorMessage as Se,extractApiError as Ce,isApiError as we,isNoResponse as Te,toFieldPath as Ee}from"./errors/extractApiError.js";import{configureFormatters as De,getFormatterConfig as Oe}from"./formatters/formatConfig.js";import{formatCurrency as ke}from"./formatters/currency.js";import{addDays as Ae}from"./formatters/dateMath.js";import{formatDate as je,formatDateTime as Me,formatMinor as Ne,formatNumber as Pe,formatPercent as Fe,formatRelative as Ie,formatTime as Le}from"./formatters/house.js";import{initWebority as Re}from"./initSDK.js";import{createApiBaseQuery as ze}from"./query/apiBaseQuery.js";import{APP_API_DEFAULTS as Be,createAppApi as Ve}from"./query/createAppApi.js";import{setupApiListeners as He}from"./query/listeners.js";import{buildListQuery as Ue,getNextPageParam as We,getPreviousPageParam as Ge,hasNextPage as Ke,hasPreviousPage as qe}from"./query/paging.js";import{LIST_TAG_ID as Je,itemTag as Ye,listTag as Xe,providesList as Ze,providesPagedList as Qe}from"./query/tags.js";import{errorToastMiddleware as $e,isSilentRejection as et}from"./redux/errorToastMiddleware.js";import{createRootReducer as tt,resetState as nt}from"./redux/rootReducer.js";import{SERIALIZABLE_IGNORED_ACTION_PATHS as rt}from"./redux/serializableCheck.js";import{hasRecentlyReloaded as it,importWithReload as at,isChunkLoadError as ot,lazyWithReload as st,markReloaded as ct}from"./router/chunkReload.js";import{hasPermission as lt}from"./router/permissions.js";import{RETURN_TO_PARAM as ut,buildLoginPath as dt,getReturnTo as ft,toSafeReturnTo as pt}from"./router/returnTo.js";import{PublicOnly as mt,RequireAuth as ht,RequirePermission as gt}from"./router/guards.js";import{publicOnly as _t,requireAuth as vt,requirePermission as yt,withGuards as bt}from"./router/loaders.js";import{classifyRouteError as xt,useRouteErrorReport as St}from"./router/routeError.js";import{staticUrl as Ct}from"./static/index.js";import{Storage as wt,isStorageAvailable as Tt,setStorageImplementation as Et,syncStorage as Dt}from"./storage/index.js";import{isBuildBelowMinimum as Ot,parseBuildNumber as kt}from"./versionCheck/buildNumber.js";import{installReloadOnNavigate as At,isUpdateAvailable as jt,useVersionCheck as Mt}from"./versionCheck/index.js";export{g as ACCESS_TOKEN_KEY,L as ACCOUNT_ID_HEADER,Be as APP_API_DEFAULTS,R as CLIENT_BUILD_HEADER,z as CLIENT_KIND,B as CLIENT_KIND_HEADER,me as CONTRACT_ERROR_CODE,e as DEFAULT_CORRELATION_ID_HEADER,t as DEFAULT_LOG_LEVEL,n as DEFAULT_RETRIES,r as DEFAULT_TIMEOUT_MS,X as IDEMPOTENCY_KEY_HEADER,_ as LEGACY_REFRESH_TOKEN_LIFETIME_MS,Je as LIST_TAG_ID,c as Logger,H as MIN_APP_VERSION_HEADER,he as NETWORK_CODE,ge as OFFLINE_MESSAGE,mt as PublicOnly,ne as REFRESH_LOCK_NAME,v as REFRESH_TOKEN_KEY,_e as REQUEST_CANCELED_CODE,ut as RETURN_TO_PARAM,de as RequestOfflineError,ht as RequireAuth,gt as RequirePermission,rt as SERIALIZABLE_IGNORED_ACTION_PATHS,ve as SERVER_FAILURE_MESSAGE,fe as SESSION_TERMINATION_CODES,y as SESSION_USER_KEY,ae as SIGN_OUT_REASON_HEADER,wt as Storage,ye as TIMEOUT_CODE,be as TIMEOUT_MESSAGE,xe as UNEXPECTED_MESSAGE,q as WORKSPACE_CHANGED_CODE,J as WorkspaceChangedError,Ae as addDays,U as addMinAppVersionListener,N as addNetworkStatusListener,b as addSessionEndedListener,Se as apiErrorMessage,G as applyRequestDefaults,Z as attachRetry,Ue as buildListQuery,dt as buildLoginPath,xt as classifyRouteError,x as clearSession,De as configureFormatters,l as configureLogger,ze as createApiBaseQuery,Ve as createAppApi,tt as createRootReducer,p as decodeJWT,$e as errorToastMiddleware,Ce as extractApiError,ke as formatCurrency,je as formatDate,Me as formatDateTime,Ne as formatMinor,Pe as formatNumber,Fe as formatPercent,Ie as formatRelative,Le as formatTime,V as getClientBuild,i as getConfig,a as getConfigValue,u as getDeviceContext,Oe as getFormatterConfig,m as getJWTExpiry,S as getKeepSignedIn,W as getMinAppVersion,P as getNetworkStatus,We as getNextPageParam,Ge as getPreviousPageParam,ft as getReturnTo,C as getSessionUser,w as getToken,Ke as hasNextPage,lt as hasPermission,qe as hasPreviousPage,it as hasRecentlyReloaded,T as hasSession,E as hasSessionEndedInTab,at as importWithReload,pe as initUserAuth,Re as initWebority,oe as injectStore,se as injectUserAuth,At as installReloadOnNavigate,we as isApiError,Ot as isBuildBelowMinimum,ot as isChunkLoadError,h as isJWTExpired,Q as isNeverSentError,Te as isNoResponse,$ as isRetryableFailure,ee as isRetryableStatus,et as isSilentRejection,Tt as isStorageAvailable,jt as isUpdateAvailable,Y as isWorkspaceChangedError,Ye as itemTag,st as lazyWithReload,Xe as listTag,ct as markReloaded,K as newCorrelationId,kt as parseBuildNumber,Ze as providesList,Qe as providesPagedList,ie as publicClient,_t as publicOnly,ce as refreshAccessToken,D as removeSessionUser,O as removeToken,vt as requireAuth,yt as requirePermission,o as resetConfig,le as resetRefreshState,nt as resetState,te as retryAfterMs,s as setConfig,d as setDeviceContext,k as setKeepSignedIn,A as setLegacyTokenKeys,F as setNetworkStatusImplementation,f as setRemoteLogger,Et as setStorageImplementation,He as setupApiListeners,Ct as staticUrl,j as storeSessionUser,M as storeToken,Dt as syncStorage,Ee as toFieldPath,pt as toSafeReturnTo,I as useNetworkStatus,St as useRouteErrorReport,Mt as useVersionCheck,ue as userClient,re as withCrossTabRefreshLock,bt as withGuards};
1
+ import{DEFAULT_CORRELATION_ID_HEADER as e,DEFAULT_LOG_LEVEL as t,DEFAULT_RETRIES as n,DEFAULT_TIMEOUT_MS as r,getConfig as i,getConfigValue as a,resetConfig as o,setConfig as s}from"./config/index.js";import{Logger as c,configureLogger as l,getDeviceContext as u,setDeviceContext as d,setRemoteLogger as f}from"./logger/logger.js";import{decodeJWT as p,getJWTExpiry as m,isJWTExpired as h}from"./auth/jwt.js";import{ACCESS_TOKEN_KEY as g,LEGACY_REFRESH_TOKEN_LIFETIME_MS as _,REFRESH_TOKEN_KEY as v,SESSION_USER_KEY as y,addSessionEndedListener as b,clearSession as x,getKeepSignedIn as S,getSessionUser as C,getToken as w,hasSession as T,hasSessionEndedInTab as E,removeSessionUser as D,removeToken as O,setKeepSignedIn as k,setLegacyTokenKeys as A,storeSessionUser as j,storeToken as M}from"./auth/authStore.js";import{addNetworkStatusListener as N,getNetworkStatus as P,setNetworkStatusImplementation as F,useNetworkStatus as I}from"./network/networkStatus.js";import{ACCOUNT_ID_HEADER as L,CLIENT_BUILD_HEADER as R,CLIENT_KIND as z,CLIENT_KIND_HEADER as B,getClientBuild as V}from"./api/clientHeaders.js";import{MIN_APP_VERSION_HEADER as H,addMinAppVersionListener as U,getMinAppVersion as W}from"./api/minAppVersion.js";import{applyRequestDefaults as G,newCorrelationId as K}from"./api/requestDefaults.js";import{WORKSPACE_CHANGED_CODE as q,WorkspaceChangedError as J,isWorkspaceChangedError as Y}from"./api/workspaceChanged.js";import{IDEMPOTENCY_KEY_HEADER as X,attachRetry as Z,isNeverSentError as Q,isRetryableFailure as $,isRetryableStatus as ee,retryAfterMs as te}from"./api/retry.js";import{REFRESH_LOCK_NAME as ne,withCrossTabRefreshLock as re}from"./api/crossTabRefreshLock.js";import ie from"./api/publicClient.js";import{SIGN_OUT_REASON_HEADER as ae,injectStore as oe,injectUserAuth as se,refreshAccessToken as ce,resetRefreshState as le}from"./api/tokenRefresh.js";import ue,{RequestOfflineError as de,SESSION_TERMINATION_CODES as fe}from"./api/userClient.js";import{initUserAuth as pe}from"./initUserAuth.js";import{CONTRACT_ERROR_CODE as me,NETWORK_CODE as he,OFFLINE_CODE as ge,OFFLINE_MESSAGE as _e,REQUEST_CANCELED_CODE as ve,SERVER_FAILURE_MESSAGE as ye,TIMEOUT_CODE as be,TIMEOUT_MESSAGE as xe,UNEXPECTED_MESSAGE as Se,UNREACHABLE_MESSAGE as Ce,apiErrorMessage as we,extractApiError as Te,isApiError as Ee,isNoResponse as De,toFieldPath as Oe}from"./errors/extractApiError.js";import{configureFormatters as ke,getFormatterConfig as Ae}from"./formatters/formatConfig.js";import{formatCurrency as je}from"./formatters/currency.js";import{addDays as Me}from"./formatters/dateMath.js";import{formatDate as Ne,formatDateTime as Pe,formatMinor as Fe,formatNumber as Ie,formatPercent as Le,formatRelative as Re,formatTime as ze}from"./formatters/house.js";import{initWebority as Be}from"./initSDK.js";import{createApiBaseQuery as Ve}from"./query/apiBaseQuery.js";import{APP_API_DEFAULTS as He,createAppApi as Ue}from"./query/createAppApi.js";import{setupApiListeners as We}from"./query/listeners.js";import{buildListQuery as Ge,getNextPageParam as Ke,getPreviousPageParam as qe,hasNextPage as Je,hasPreviousPage as Ye}from"./query/paging.js";import{LIST_TAG_ID as Xe,itemTag as Ze,listTag as Qe,providesList as $e,providesPagedList as et}from"./query/tags.js";import{errorToastMiddleware as tt,isSilentRejection as nt}from"./redux/errorToastMiddleware.js";import{createRootReducer as rt,resetState as it}from"./redux/rootReducer.js";import{SERIALIZABLE_IGNORED_ACTION_PATHS as at}from"./redux/serializableCheck.js";import{hasRecentlyReloaded as ot,importWithReload as st,isChunkLoadError as ct,lazyWithReload as lt,markReloaded as ut}from"./router/chunkReload.js";import{hasPermission as dt}from"./router/permissions.js";import{RETURN_TO_PARAM as ft,buildLoginPath as pt,getReturnTo as mt,toSafeReturnTo as ht}from"./router/returnTo.js";import{PublicOnly as gt,RequireAuth as _t,RequirePermission as vt}from"./router/guards.js";import{publicOnly as yt,requireAuth as bt,requirePermission as xt,withGuards as St}from"./router/loaders.js";import{classifyRouteError as Ct,useRouteErrorReport as wt}from"./router/routeError.js";import{staticUrl as Tt}from"./static/index.js";import{Storage as Et,isStorageAvailable as Dt,setStorageImplementation as Ot,syncStorage as kt}from"./storage/index.js";import{isBuildBelowMinimum as At,parseBuildNumber as jt}from"./versionCheck/buildNumber.js";import{installReloadOnNavigate as Mt,isUpdateAvailable as Nt,useVersionCheck as Pt}from"./versionCheck/index.js";export{g as ACCESS_TOKEN_KEY,L as ACCOUNT_ID_HEADER,He as APP_API_DEFAULTS,R as CLIENT_BUILD_HEADER,z as CLIENT_KIND,B as CLIENT_KIND_HEADER,me as CONTRACT_ERROR_CODE,e as DEFAULT_CORRELATION_ID_HEADER,t as DEFAULT_LOG_LEVEL,n as DEFAULT_RETRIES,r as DEFAULT_TIMEOUT_MS,X as IDEMPOTENCY_KEY_HEADER,_ as LEGACY_REFRESH_TOKEN_LIFETIME_MS,Xe as LIST_TAG_ID,c as Logger,H as MIN_APP_VERSION_HEADER,he as NETWORK_CODE,ge as OFFLINE_CODE,_e as OFFLINE_MESSAGE,gt as PublicOnly,ne as REFRESH_LOCK_NAME,v as REFRESH_TOKEN_KEY,ve as REQUEST_CANCELED_CODE,ft as RETURN_TO_PARAM,de as RequestOfflineError,_t as RequireAuth,vt as RequirePermission,at as SERIALIZABLE_IGNORED_ACTION_PATHS,ye as SERVER_FAILURE_MESSAGE,fe as SESSION_TERMINATION_CODES,y as SESSION_USER_KEY,ae as SIGN_OUT_REASON_HEADER,Et as Storage,be as TIMEOUT_CODE,xe as TIMEOUT_MESSAGE,Se as UNEXPECTED_MESSAGE,Ce as UNREACHABLE_MESSAGE,q as WORKSPACE_CHANGED_CODE,J as WorkspaceChangedError,Me as addDays,U as addMinAppVersionListener,N as addNetworkStatusListener,b as addSessionEndedListener,we as apiErrorMessage,G as applyRequestDefaults,Z as attachRetry,Ge as buildListQuery,pt as buildLoginPath,Ct as classifyRouteError,x as clearSession,ke as configureFormatters,l as configureLogger,Ve as createApiBaseQuery,Ue as createAppApi,rt as createRootReducer,p as decodeJWT,tt as errorToastMiddleware,Te as extractApiError,je as formatCurrency,Ne as formatDate,Pe as formatDateTime,Fe as formatMinor,Ie as formatNumber,Le as formatPercent,Re as formatRelative,ze as formatTime,V as getClientBuild,i as getConfig,a as getConfigValue,u as getDeviceContext,Ae as getFormatterConfig,m as getJWTExpiry,S as getKeepSignedIn,W as getMinAppVersion,P as getNetworkStatus,Ke as getNextPageParam,qe as getPreviousPageParam,mt as getReturnTo,C as getSessionUser,w as getToken,Je as hasNextPage,dt as hasPermission,Ye as hasPreviousPage,ot as hasRecentlyReloaded,T as hasSession,E as hasSessionEndedInTab,st as importWithReload,pe as initUserAuth,Be as initWebority,oe as injectStore,se as injectUserAuth,Mt as installReloadOnNavigate,Ee as isApiError,At as isBuildBelowMinimum,ct as isChunkLoadError,h as isJWTExpired,Q as isNeverSentError,De as isNoResponse,$ as isRetryableFailure,ee as isRetryableStatus,nt as isSilentRejection,Dt as isStorageAvailable,Nt as isUpdateAvailable,Y as isWorkspaceChangedError,Ze as itemTag,lt as lazyWithReload,Qe as listTag,ut as markReloaded,K as newCorrelationId,jt as parseBuildNumber,$e as providesList,et as providesPagedList,ie as publicClient,yt as publicOnly,ce as refreshAccessToken,D as removeSessionUser,O as removeToken,bt as requireAuth,xt as requirePermission,o as resetConfig,le as resetRefreshState,it as resetState,te as retryAfterMs,s as setConfig,d as setDeviceContext,k as setKeepSignedIn,A as setLegacyTokenKeys,F as setNetworkStatusImplementation,f as setRemoteLogger,Ot as setStorageImplementation,We as setupApiListeners,Tt as staticUrl,j as storeSessionUser,M as storeToken,kt as syncStorage,Oe as toFieldPath,ht as toSafeReturnTo,I as useNetworkStatus,wt as useRouteErrorReport,Pt as useVersionCheck,ue as userClient,re as withCrossTabRefreshLock,St as withGuards};
@@ -0,0 +1 @@
1
+ function e(e,...t){console.warn(e,...t)}export{e as devWarn};
@@ -12,9 +12,9 @@
12
12
  * legacy `error`, `title`, then `Request failed (<status>)`. `title` is last because it is
13
13
  * the ProblemDetails category ("Bad Request"), not the curated sentence.
14
14
  *
15
- * Two things never become `message`: a 5xx body (our failure, nothing the user can act on)
16
- * and anything that reads like an exception dump. The server's text goes on `detail` for
17
- * the logger instead.
15
+ * Two things never become `message`: a 5xx body unless it carries a code other than
16
+ * `internal_error` and a curated message, and anything that reads like an exception dump.
17
+ * The server's text goes on `detail` for the logger instead.
18
18
  */
19
19
  export interface ApiError {
20
20
  /** Stable snake_case branch key from the server (`not_found`, `validation_failed`). Branch on it, never render it. */
@@ -34,6 +34,7 @@ export interface ApiError {
34
34
  }
35
35
  export declare const SERVER_FAILURE_MESSAGE = "Something went wrong on our side. Please try again in a moment.";
36
36
  export declare const OFFLINE_MESSAGE = "You appear to be offline. Check your connection and try again.";
37
+ export declare const UNREACHABLE_MESSAGE = "We couldn't reach the server. Check your connection and try again.";
37
38
  export declare const TIMEOUT_MESSAGE = "That took too long to respond. Check your connection and try again.";
38
39
  export declare const UNEXPECTED_MESSAGE = "Something went wrong. Please try again.";
39
40
  /** `code` for a request the caller cancelled (axios `CanceledError`). Never toasted. */
@@ -42,8 +43,10 @@ export declare const REQUEST_CANCELED_CODE = "request_canceled";
42
43
  export declare const CONTRACT_ERROR_CODE = "contract_error";
43
44
  /** `code` for a request that got no answer in time (axios `ECONNABORTED` / `ETIMEDOUT`). `offline` is true. */
44
45
  export declare const TIMEOUT_CODE = "timeout";
45
- /** `code` for a request that never reached the server (offline, DNS, CORS, a dropped connection). `offline` is true. */
46
+ /** `code` for a request that never reached the server while the browser reported a connection (DNS, CORS, a dropped connection). `offline` is true. */
46
47
  export declare const NETWORK_CODE = "network";
48
+ /** `code` for a request that never reached the server while the browser reported no network. `offline` is true. */
49
+ export declare const OFFLINE_CODE = "offline";
47
50
  /** `Items[0].UnitPrice` -> `items[0].unitPrice`; `$.email` (System.Text.Json path) -> `email`. */
48
51
  export declare const toFieldPath: (key: string) => string;
49
52
  export declare const isApiError: (value: unknown) => value is ApiError;
@@ -56,9 +59,10 @@ export declare const isNoResponse: (error: unknown) => boolean;
56
59
  /**
57
60
  * The sentence a screen shows for a failure: the server's own curated message when it sent one,
58
61
  * otherwise the screen's `fallback` ("We couldn't save the project."), otherwise the library's
59
- * generic sentence. A lost answer always reads as the connection message, because "check your
60
- * connection" is more accurate than any screen's fallback. A 5xx, a cancelled request and a body
61
- * with no usable sentence count as "the server said nothing usable".
62
+ * generic sentence. A lost answer always reads as its connection message, because "check your
63
+ * connection" is more accurate than any screen's fallback, and so does a 5xx with a curated body.
64
+ * A 5xx without one, a cancelled request and a body with no usable sentence count as "the server
65
+ * said nothing usable".
62
66
  *
63
67
  * `fallback: null` is the "say nothing" mode, for a screen that shows only what the server
64
68
  * curated (a live panel that keeps its last result): it returns null when the server said
@@ -1,2 +1,2 @@
1
1
  export type { ApiError } from "./extractApiError";
2
- 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 "./extractApiError";
2
+ export { apiErrorMessage, CONTRACT_ERROR_CODE, extractApiError, isApiError, isNoResponse, NETWORK_CODE, OFFLINE_CODE, OFFLINE_MESSAGE, REQUEST_CANCELED_CODE, SERVER_FAILURE_MESSAGE, TIMEOUT_CODE, TIMEOUT_MESSAGE, toFieldPath, UNEXPECTED_MESSAGE, UNREACHABLE_MESSAGE, } from "./extractApiError";
@@ -3,7 +3,7 @@
3
3
  * `signDisplay`, ...), passed through to Intl.NumberFormat.
4
4
  */
5
5
  export interface FormatCurrencyOptions extends Omit<Intl.NumberFormatOptions, "style" | "currency"> {
6
- /** ISO 4217 currency code. Defaults to `'INR'`. */
6
+ /** ISO 4217 code; pass it on every call, since a call without one warns now and throws from 0.78.0. */
7
7
  currency?: string;
8
8
  /** BCP-47 locale tag. Defaults to the configured locale, else `'en-IN'` (Indian numbering system). */
9
9
  locale?: string;
@@ -20,9 +20,10 @@ export interface FormatCurrencyOptions extends Omit<Intl.NumberFormatOptions, "s
20
20
  empty?: string;
21
21
  }
22
22
  /**
23
- * Format an amount as currency. Defaults to **INR** with Indian numbering (`en-IN`),
24
- * which matches the standard convention across Webority projects. Called with no
25
- * options: "₹1,50,000" for 150000, "₹1,234.50" for 1234.5, and `''` for a missing amount.
23
+ * Format an amount as currency, with Indian numbering (`en-IN`), which matches the standard
24
+ * convention across Webority projects. Pass currency 'INR' on every call: a call without one
25
+ * warns and prints INR for now. With currency 'INR': "₹1,50,000" for 150000, "₹1,234.50" for
26
+ * 1234.5, and `''` for a missing amount.
26
27
  * Once the app configures a locale (`configureFormatters({ locale })`), the amount is
27
28
  * written in that locale and a missing amount prints the configured placeholder ("-").
28
29
  * A configured `numberStyle` sets the decimal mark and group separator; the locale keeps
@@ -31,10 +32,10 @@ export interface FormatCurrencyOptions extends Omit<Intl.NumberFormatOptions, "s
31
32
  * use `formatMinor`.
32
33
  *
33
34
  * @example
34
- * formatCurrency(150000) // ₹1,50,000
35
- * formatCurrency(1234.5) // ₹1,234.50
36
- * formatCurrency(99, { currency: 'USD', locale: 'en-US' }) // $99
37
- * formatCurrency(150000, { stripSymbol: true }) // 1,50,000
38
- * formatCurrency(1500000, { notation: 'compact' }) // ₹15L
35
+ * formatCurrency(150000, { currency: 'INR' }) // ₹1,50,000
36
+ * formatCurrency(1234.5, { currency: 'INR' }) // ₹1,234.50
37
+ * formatCurrency(99, { currency: 'USD', locale: 'en-US' }) // $99
38
+ * formatCurrency(150000, { currency: 'INR', stripSymbol: true }) // 1,50,000
39
+ * formatCurrency(1500000, { currency: 'INR', notation: 'compact' }) // ₹15L
39
40
  */
40
41
  export declare const formatCurrency: (amount: number | string | null | undefined, options?: FormatCurrencyOptions) => string;
@@ -1,37 +1,3 @@
1
- /**
2
- * The house formatters: DD-MMM-YYYY dates, IST by default or the viewer's own
3
- * zone with a label, Indian digit grouping by default, money in minor units,
4
- * and one empty placeholder. Byte-identical in @webority/mobile-core and
5
- * @webority/web-core.
6
- *
7
- * Same output on Hermes and in every browser is the design constraint, so the
8
- * text is assembled here rather than by Intl. Engines disagree on month
9
- * abbreviations ("Sep" or "Sept"), on the space before AM/PM (a plain or a
10
- * narrow no-break space), on zone names ("IST" or "GMT+5:30") and on which
11
- * Intl options exist at all (Hermes has no RelativeTimeFormat and no
12
- * trailingZeroDisplay). IST and the viewer's zone are therefore computed with
13
- * plain Date arithmetic; Intl is used only to read the wall clock of an
14
- * explicitly named IANA zone, through formatToParts with numeric fields, to
15
- * read the locale's 12- or 24-hour clock, and where a caller asks for Intl
16
- * output itself (Intl number options, `formatRelative({ intl: true })`).
17
- *
18
- * Called with no options (house defaults: zone IST, locale en-IN, empty "-"):
19
- * - formatDate(v) "08-Apr-2026"; formatTime(v) "8:05 PM"; formatDateTime(v) "08-Apr-2026, 8:05 PM";
20
- * - formatRelative(v) "5 minutes ago", "in 3 days", "just now";
21
- * - formatNumber(v) "1,23,456.789" (Indian grouping, up to 3 decimals);
22
- * - formatPercent(0.42) "42%"; formatMinor(15000000) "₹1,50,000.00";
23
- * - a missing or unreadable value "-".
24
- *
25
- * With a configured locale (`configureFormatters({ locale })`), the words and separators come
26
- * from Intl for that locale and the date order stays DD-MMM-YYYY. For en-IN in the viewer zone:
27
- * "08-Sept-2026", "08:05 pm", "08-Sept-2026, 08:05 pm IST", "yesterday", "12,34,567.891",
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".
34
- */
35
1
  import { type NumberGrouping, type ZoneMode } from "./formatConfig";
36
2
  /** A date the house formatters accept; null, undefined and "" read as missing. */
37
3
  export type DateValue = Date | string | number | null | undefined;
@@ -96,7 +62,7 @@ export interface FormatPercentOptions extends FormatNumberOptions {
96
62
  scale?: "ratio" | "percent";
97
63
  }
98
64
  export interface FormatMinorOptions {
99
- /** ISO 4217 code. Defaults to `'INR'`. */
65
+ /** ISO 4217 code; pass it on every call, since a call without one warns now and throws from 0.78.0. */
100
66
  currency?: string;
101
67
  /** Defaults to Indian grouping for INR and international grouping for every other currency. */
102
68
  grouping?: NumberGrouping;
@@ -138,7 +104,7 @@ export declare const formatNumber: (value: number | string | null | undefined, o
138
104
  export declare const formatPercent: (value: number | string | null | undefined, options?: FormatPercentOptions) => string;
139
105
  /**
140
106
  * Money held in minor units (paise, cents), which is how every API carries
141
- * it: formatMinor(15000000) gives "₹1,50,000.00". The split into whole and
107
+ * it: formatMinor(15000000, { currency: "INR" }) gives "₹1,50,000.00". The split into whole and
142
108
  * fractional units is done on the integer's digits, so no floating-point
143
109
  * division can shift a paisa. A fractional input is rounded to the nearest
144
110
  * minor unit. A currency without a known symbol prints its code: "AED 1,000.00".
@@ -0,0 +1,2 @@
1
+ export declare function devWarn(message: string, ...optionalParams: unknown[]): void;
2
+ export declare function devError(message: string, ...optionalParams: unknown[]): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/web-core",
3
- "version": "0.76.0",
3
+ "version": "0.77.0",
4
4
  "description": "Platform layer for Webority React web portals: HTTP clients with single-flight token refresh, auth store, API error extraction, RTK Query base query, logger, formatters, storage, version check and route guards. No UI.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",