@webority/mobile-core 0.122.0 → 0.124.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 +63 -1
- package/lib/commonjs/api/clientHeaders.js +1 -1
- package/lib/commonjs/api/idempotencyKey.js +1 -0
- package/lib/commonjs/clipboard/index.js +1 -0
- package/lib/commonjs/errors/extractApiError.js +1 -1
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/initUserAuth.js +1 -1
- package/lib/commonjs/outbox/errors.js +1 -0
- package/lib/commonjs/outbox/files.js +1 -0
- package/lib/commonjs/outbox/index.js +1 -0
- package/lib/commonjs/outbox/outbox.js +1 -0
- package/lib/commonjs/outbox/types.js +1 -0
- package/lib/commonjs/query/apiBaseQuery.js +1 -1
- package/lib/commonjs/redux/errorToastMiddleware.js +1 -1
- package/lib/module/api/clientHeaders.js +1 -1
- package/lib/module/api/idempotencyKey.js +1 -0
- package/lib/module/clipboard/index.js +1 -0
- package/lib/module/errors/extractApiError.js +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/initUserAuth.js +1 -1
- package/lib/module/outbox/errors.js +1 -0
- package/lib/module/outbox/files.js +1 -0
- package/lib/module/outbox/index.js +1 -0
- package/lib/module/outbox/outbox.js +1 -0
- package/lib/module/outbox/types.js +1 -0
- package/lib/module/query/apiBaseQuery.js +1 -1
- package/lib/module/redux/errorToastMiddleware.js +1 -1
- package/lib/typescript/commonjs/api/clientHeaders.d.ts +6 -1
- package/lib/typescript/commonjs/api/idempotencyKey.d.ts +2 -0
- package/lib/typescript/commonjs/clipboard/index.d.ts +3 -0
- package/lib/typescript/commonjs/errors/extractApiError.d.ts +3 -2
- package/lib/typescript/commonjs/index.d.ts +2 -0
- package/lib/typescript/commonjs/initUserAuth.d.ts +10 -2
- package/lib/typescript/commonjs/outbox/errors.d.ts +10 -0
- package/lib/typescript/commonjs/outbox/files.d.ts +5 -0
- package/lib/typescript/commonjs/outbox/index.d.ts +4 -0
- package/lib/typescript/commonjs/outbox/outbox.d.ts +3 -0
- package/lib/typescript/commonjs/outbox/types.d.ts +115 -0
- package/lib/typescript/commonjs/query/apiBaseQuery.d.ts +13 -2
- package/lib/typescript/commonjs/redux/errorToastMiddleware.d.ts +5 -1
- package/lib/typescript/module/api/clientHeaders.d.ts +6 -1
- package/lib/typescript/module/api/idempotencyKey.d.ts +2 -0
- package/lib/typescript/module/clipboard/index.d.ts +3 -0
- package/lib/typescript/module/errors/extractApiError.d.ts +3 -2
- package/lib/typescript/module/index.d.ts +2 -0
- package/lib/typescript/module/initUserAuth.d.ts +10 -2
- package/lib/typescript/module/outbox/errors.d.ts +10 -0
- package/lib/typescript/module/outbox/files.d.ts +5 -0
- package/lib/typescript/module/outbox/index.d.ts +4 -0
- package/lib/typescript/module/outbox/outbox.d.ts +3 -0
- package/lib/typescript/module/outbox/types.d.ts +115 -0
- package/lib/typescript/module/query/apiBaseQuery.d.ts +13 -2
- package/lib/typescript/module/redux/errorToastMiddleware.d.ts +5 -1
- package/package.json +26 -1
package/README.md
CHANGED
|
@@ -42,6 +42,12 @@ import { createApiBaseQuery, createAppApi, setupApiListeners } from '@webority/m
|
|
|
42
42
|
Metro resolves requires statically, so anything reachable from the main barrel is bundled for
|
|
43
43
|
every consumer. Keeping these off it is what makes their peers genuinely optional.
|
|
44
44
|
|
|
45
|
+
`initUserAuth` takes an optional `installationId` provider: with it, `publicClient` and `userClient`
|
|
46
|
+
send the header `Installation-Id` on every request, resolved once on the first request and kept in
|
|
47
|
+
memory; without it no header goes out. The clients never import `/installation`, so they load
|
|
48
|
+
without the optional `expo-crypto` peer; the app passes the function in:
|
|
49
|
+
`initUserAuth(store, { ..., installationId: getOrCreateInstallationId })`.
|
|
50
|
+
|
|
45
51
|
`/query` is the RTK Query layer; it needs `@reduxjs/toolkit` (2.12 or later) and `react-redux`,
|
|
46
52
|
both optional peers. One `createApi` per app, built with `createAppApi` and the base query over
|
|
47
53
|
the library's clients, so refresh, retry, the offline check and the `extractApiError` failure
|
|
@@ -71,7 +77,13 @@ export const apiSlice = createAppApi({
|
|
|
71
77
|
and this library's network status to online and offline; RTK's own defaults listen to `window`
|
|
72
78
|
events that never fire on a device. A call marked `silent: true`, or an endpoint with
|
|
73
79
|
`extraOptions: { silent: true }`, carries `silent` on `action.meta.baseQueryMeta`, which the
|
|
74
|
-
error toast middleware skips.
|
|
80
|
+
error toast middleware skips. A call that handles some statuses itself passes `expectedStatuses: [404]`
|
|
81
|
+
(or `extraOptions: { expectedStatuses: [404] }`): a failure with one of them is logged at info, never
|
|
82
|
+
recorded as an error, and the error toast middleware skips it, as it does `silent`.
|
|
83
|
+
`paramsFormat: "repeat" | "brackets" | "comma"`, in the argument or in `extraOptions`, sets how a list in
|
|
84
|
+
`params` reaches the query string: `repeat` sends `a=1&a=2`, `brackets` sends `a[]=1&a[]=2`, `comma`
|
|
85
|
+
sends `a=1,2`. A scalar encodes the same in every format, and without it the client's own serializing
|
|
86
|
+
applies.
|
|
75
87
|
|
|
76
88
|
`/push` registers the phone for push notifications. It needs `expo-notifications`, an optional
|
|
77
89
|
peer, and reports `unavailable` without it or in Expo Go. Call `initPush` once at startup with
|
|
@@ -129,6 +141,56 @@ await offlineQueries.clear();
|
|
|
129
141
|
A restored answer shows at once without a fetch, so set `refetchOnMountOrArgChange: true` on each
|
|
130
142
|
kept endpoint: a screen that mounts then asks the server again and refreshes the restored data.
|
|
131
143
|
|
|
144
|
+
### Outbox
|
|
145
|
+
|
|
146
|
+
`@webority/mobile-core/outbox` keeps writes that must survive no signal, such as a support ticket,
|
|
147
|
+
a reply or a form. The write is stored on the phone first, then sent. Create one outbox per app,
|
|
148
|
+
over the signed-in client:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
// services/outbox.ts
|
|
152
|
+
import { userClient } from '@webority/mobile-core';
|
|
153
|
+
import { createOutbox } from '@webority/mobile-core/outbox';
|
|
154
|
+
|
|
155
|
+
export const outbox = createOutbox({ http: userClient });
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`send({ queue, label, request })` stores the entry, copying any file part into the outbox's own
|
|
159
|
+
storage, then tries it once. `label` is what a list shows: the ticket subject, or the first words of
|
|
160
|
+
a reply. `list(queue)` returns the signed-in person's entries of one queue, oldest first.
|
|
161
|
+
|
|
162
|
+
Request rules:
|
|
163
|
+
|
|
164
|
+
- Every request carries an `Idempotency-Key` header holding a uuid, so a retry after a lost answer
|
|
165
|
+
cannot create a second record.
|
|
166
|
+
- Never set `Authorization` or `Account-Id`. The outbox refuses both and sets the workspace itself.
|
|
167
|
+
- The body is JSON, or multipart with text fields and file parts.
|
|
168
|
+
|
|
169
|
+
What the result means:
|
|
170
|
+
|
|
171
|
+
- `Sent`: the server accepted the request. `httpStatus` and `data` carry its answer, and the entry is
|
|
172
|
+
removed.
|
|
173
|
+
- `Queued`: no answer came back yet (no signal, a timeout or a transient failure). The entry waits
|
|
174
|
+
and is sent again.
|
|
175
|
+
- `Failed`: the server refused the request on the first try. The entry is deleted and `failure`
|
|
176
|
+
carries `code`, `message` and `status`. A queued entry the server refuses later stays listed in
|
|
177
|
+
state `Failed` with its `lastFailure`, until `retry(id)` or `discard(id)`.
|
|
178
|
+
|
|
179
|
+
Entries belong to the person who was signed in when they were sent. `list` and `flush` see only
|
|
180
|
+
that person's entries, so the next person on the phone never sees or sends them. A send while
|
|
181
|
+
signed out throws `OutboxSignedOutError`.
|
|
182
|
+
|
|
183
|
+
Limits: an owner holds at most 50 entries, and a send beyond that throws `OutboxFullError`. An
|
|
184
|
+
entry older than 14 days is deleted with its files.
|
|
185
|
+
|
|
186
|
+
Sending happens while the app is open. `flush()` sends each due entry of the signed-in owner, one
|
|
187
|
+
at a time, oldest first. Nothing is sent in the background; a queued entry waits for the next time
|
|
188
|
+
the app is open and online. `subscribe(listener)` reports `changed`, `sent` and `failed` events, so
|
|
189
|
+
a screen can refresh.
|
|
190
|
+
|
|
191
|
+
The outbox needs two peers: `expo-sqlite` (the store) and `expo-file-system` (the copies of file
|
|
192
|
+
parts). Install them with `npx expo install expo-sqlite expo-file-system`.
|
|
193
|
+
|
|
132
194
|
### Notification buttons
|
|
133
195
|
|
|
134
196
|
A push names a category; the category's buttons are registered on the phone. Register them at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.stampAccountId=exports.readAccountId=exports.getClientBuild=exports.applyClientHeaders=exports.CLIENT_KIND_HEADER=exports.CLIENT_KIND=exports.CLIENT_BUILD_HEADER=exports.CLIENT_APP_HEADER=exports.APP_BUILD_HEADER=exports.ACCOUNT_ID_HEADER=void 0;var _index=require("../config/index.js"),_appBuild=require("../versionCheck/appBuild.js");const CLIENT_BUILD_HEADER=exports.CLIENT_BUILD_HEADER="Client-Build",APP_BUILD_HEADER=exports.APP_BUILD_HEADER="App-Build",CLIENT_KIND_HEADER=exports.CLIENT_KIND_HEADER="Client-Kind",CLIENT_APP_HEADER=exports.CLIENT_APP_HEADER="Client-App",ACCOUNT_ID_HEADER=exports.ACCOUNT_ID_HEADER="Account-Id",CLIENT_KIND=exports.CLIENT_KIND="MobileApp",getClientBuild=()=>{const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.stampAccountId=exports.setInstallationIdProvider=exports.readAccountId=exports.getClientBuild=exports.applyClientHeaders=exports.INSTALLATION_ID_HEADER=exports.CLIENT_KIND_HEADER=exports.CLIENT_KIND=exports.CLIENT_BUILD_HEADER=exports.CLIENT_APP_HEADER=exports.APP_BUILD_HEADER=exports.ACCOUNT_ID_HEADER=void 0;var _index=require("../config/index.js"),_appBuild=require("../versionCheck/appBuild.js");const CLIENT_BUILD_HEADER=exports.CLIENT_BUILD_HEADER="Client-Build",APP_BUILD_HEADER=exports.APP_BUILD_HEADER="App-Build",CLIENT_KIND_HEADER=exports.CLIENT_KIND_HEADER="Client-Kind",CLIENT_APP_HEADER=exports.CLIENT_APP_HEADER="Client-App",ACCOUNT_ID_HEADER=exports.ACCOUNT_ID_HEADER="Account-Id",INSTALLATION_ID_HEADER=exports.INSTALLATION_ID_HEADER="Installation-Id",CLIENT_KIND=exports.CLIENT_KIND="MobileApp",getClientBuild=()=>{const t=(0,_index.getConfigValue)("appVersion");if(!t)return null;const e=(0,_index.getConfigValue)("commit");return e?`${t}+${e}`:t};exports.getClientBuild=getClientBuild;const setIfAbsent=(t,e,n)=>{n&&!t.has(e)&&t.set(e,n)};let installationIdProvider=null,installationId=null;const setInstallationIdProvider=t=>{installationIdProvider=t,installationId=null};exports.setInstallationIdProvider=setInstallationIdProvider;const resolveInstallationId=()=>{if(!installationIdProvider)return null;if(!installationId){const t=installationIdProvider();installationId=t,t.catch(()=>{installationId===t&&(installationId=null)})}return installationId},applyClientHeaders=t=>{t.interceptors.request.use(async t=>{t.headers.has(INSTALLATION_ID_HEADER)||setIfAbsent(t.headers,INSTALLATION_ID_HEADER,await resolveInstallationId()),setIfAbsent(t.headers,CLIENT_KIND_HEADER,CLIENT_KIND),setIfAbsent(t.headers,CLIENT_APP_HEADER,(0,_index.getConfigValue)("appId")),setIfAbsent(t.headers,CLIENT_BUILD_HEADER,getClientBuild());const e=(0,_appBuild.readAppBuild)();return setIfAbsent(t.headers,APP_BUILD_HEADER,null===e?null:String(e)),t})};exports.applyClientHeaders=applyClientHeaders;const readAccountId=async t=>t&&await t()||null;exports.readAccountId=readAccountId;const stampAccountId=async(t,e)=>{if(void 0!==t._accountId)return void(t._accountId&&t.headers.set(ACCOUNT_ID_HEADER,t._accountId));const n=t.headers.get(ACCOUNT_ID_HEADER);if("string"==typeof n&&""!==n)return void(t._accountId=n);const s=await readAccountId(e);t._accountId=s,s&&t.headers.set(ACCOUNT_ID_HEADER,s)};exports.stampAccountId=stampAccountId;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.newIdempotencyKey=void 0;const cryptoApi=()=>globalThis.crypto,randomBytes16=()=>{const e=new Uint8Array(16),t=cryptoApi();if("function"==typeof t?.getRandomValues)t.getRandomValues(e);else for(let t=0;t<e.length;t+=1)e[t]=Math.floor(256*Math.random());return e},formatUuid=e=>{const t=Array.from(e,e=>e.toString(16).padStart(2,"0")).join("");return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20,32)}`},newIdempotencyKey=()=>{const e=cryptoApi();if("function"==typeof e?.randomUUID)return e.randomUUID();const t=randomBytes16();return t[6]=15&t[6]|64,t[8]=63&t[8]|128,formatUuid(t)};exports.newIdempotencyKey=newIdempotencyKey;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.copyText=void 0;const copyText=e=>require("expo-clipboard").setStringAsync(e);exports.copyText=copyText;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.UNREACHABLE_MESSAGE=exports.UNEXPECTED_MESSAGE=exports.TIMEOUT_MESSAGE=exports.TIMEOUT_CODE=exports.SERVER_FAILURE_MESSAGE=exports.REQUEST_CANCELED_CODE=exports.OFFLINE_MESSAGE=exports.OFFLINE_CODE=exports.NETWORK_CODE=exports.CONTRACT_ERROR_CODE=void 0,exports.apiErrorMessage=apiErrorMessage,exports.extractApiError=extractApiError,exports.toFieldPath=exports.isNoResponse=exports.isApiError=void 0;const SERVER_FAILURE_MESSAGE=exports.SERVER_FAILURE_MESSAGE="Something went wrong on our side. Please try again in a moment.",OFFLINE_MESSAGE=exports.OFFLINE_MESSAGE="You appear to be offline. Check your connection and try again.",TIMEOUT_MESSAGE=exports.TIMEOUT_MESSAGE="That took too long to respond. Check your connection and try again.",UNEXPECTED_MESSAGE=exports.UNEXPECTED_MESSAGE="Something went wrong. Please try again.",UNREACHABLE_MESSAGE=exports.UNREACHABLE_MESSAGE="We couldn't reach the server. Check your connection and try again.",REQUEST_CANCELED_CODE=exports.REQUEST_CANCELED_CODE="request_canceled",CONTRACT_ERROR_CODE=exports.CONTRACT_ERROR_CODE="contract_error",TIMEOUT_CODE=exports.TIMEOUT_CODE="timeout",NETWORK_CODE=exports.NETWORK_CODE="network",OFFLINE_CODE=exports.OFFLINE_CODE="offline",INTERNAL_ERROR_CODE="internal_error",MAX_MESSAGE_LENGTH=300,requestFailedMessage=e=>`Request failed (${e})`,isDict=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),nonEmptyString=e=>"string"==typeof e&&e.trim().length>0?e:null,looksLikeDiagnostics=e=>e.length>300||/^\s*</.test(e)||e.includes("\n at ")||/(Exception|StackTrace):/.test(e)||/\b(System|Microsoft)\.[A-Za-z]+\.[A-Za-z]/.test(e),userSafe=e=>{const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.UNREACHABLE_MESSAGE=exports.UNEXPECTED_MESSAGE=exports.TIMEOUT_MESSAGE=exports.TIMEOUT_CODE=exports.SERVER_FAILURE_MESSAGE=exports.REQUEST_CANCELED_CODE=exports.OFFLINE_MESSAGE=exports.OFFLINE_CODE=exports.NETWORK_CODE=exports.CONTRACT_ERROR_CODE=void 0,exports.apiErrorMessage=apiErrorMessage,exports.extractApiError=extractApiError,exports.toFieldPath=exports.isNoResponse=exports.isApiError=void 0;const SERVER_FAILURE_MESSAGE=exports.SERVER_FAILURE_MESSAGE="Something went wrong on our side. Please try again in a moment.",OFFLINE_MESSAGE=exports.OFFLINE_MESSAGE="You appear to be offline. Check your connection and try again.",TIMEOUT_MESSAGE=exports.TIMEOUT_MESSAGE="That took too long to respond. Check your connection and try again.",UNEXPECTED_MESSAGE=exports.UNEXPECTED_MESSAGE="Something went wrong. Please try again.",UNREACHABLE_MESSAGE=exports.UNREACHABLE_MESSAGE="We couldn't reach the server. Check your connection and try again.",REQUEST_CANCELED_CODE=exports.REQUEST_CANCELED_CODE="request_canceled",CONTRACT_ERROR_CODE=exports.CONTRACT_ERROR_CODE="contract_error",TIMEOUT_CODE=exports.TIMEOUT_CODE="timeout",NETWORK_CODE=exports.NETWORK_CODE="network",OFFLINE_CODE=exports.OFFLINE_CODE="offline",INTERNAL_ERROR_CODE="internal_error",MAX_MESSAGE_LENGTH=300,requestFailedMessage=e=>`Request failed (${e})`,FLEET_DEFAULT_REFUSALS={401:{code:"unauthorized",sentence:"Please sign in to continue."},403:{code:"forbidden",sentence:"You do not have access to this."}},isDict=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),nonEmptyString=e=>"string"==typeof e&&e.trim().length>0?e:null,fleetDefaultRefusalSentence=(e,t)=>{const r=FLEET_DEFAULT_REFUSALS[e];if(void 0===r||null===t||t.code!==r.code)return null;const s=nonEmptyString(t.detail);return null===s||s===r.sentence?r.sentence:null},looksLikeDiagnostics=e=>e.length>300||/^\s*</.test(e)||e.includes("\n at ")||/(Exception|StackTrace):/.test(e)||/\b(System|Microsoft)\.[A-Za-z]+\.[A-Za-z]/.test(e),userSafe=e=>{const t=nonEmptyString(e);return null===t||looksLikeDiagnostics(t)?null:t},toFieldPath=e=>e.replace(/^\$\.?/,"").split(".").map(e=>e.charAt(0).toLowerCase()+e.slice(1)).join(".");exports.toFieldPath=toFieldPath;const firstMessage=e=>{if(Array.isArray(e)){for(const t of e){const e=nonEmptyString(t);if(null!==e)return e}return null}return nonEmptyString(e)},addError=(e,t,r)=>{const s=toFieldPath(t);""===s?e.form??=r:s in e.fields||(e.fields[s]=r)},readErrors=e=>{const t={fields:{},form:null};if(Array.isArray(e)){for(const r of e){if(!isDict(r))continue;const e=nonEmptyString(r.message);null!==e&&addError(t,"string"==typeof r.field?r.field:"",e)}return t}if(!isDict(e))return t;for(const[r,s]of Object.entries(e)){const e=firstMessage(s);null!==e&&addError(t,r,e)}return t},isApiError=e=>isDict(e)&&"string"==typeof e.message&&"number"==typeof e.status&&"boolean"==typeof e.offline&&isDict(e.fieldErrors);exports.isApiError=isApiError;const build=e=>({code:null,fieldErrors:{},status:0,offline:!1,traceId:null,diagnostic:null,...e}),requestTraceId=e=>{const t=isDict(e.config)?e.config.headers:void 0;if(!isDict(t))return null;const r="function"==typeof t.get?t.get("traceparent"):t.traceparent??t.Traceparent,s="string"==typeof r?/^00-([0-9a-f]{32})-[0-9a-f]{16}-[0-9a-f]{2}$/.exec(r):null;return s?s[1]:null},fromNoResponse=e=>{const t=nonEmptyString(e.code),r=nonEmptyString(e.name),s=nonEmptyString(e.message),E=requestTraceId(e);return build("CanceledError"===r||"ERR_CANCELED"===t?{code:REQUEST_CANCELED_CODE,message:UNEXPECTED_MESSAGE,traceId:E,diagnostic:s}:"ECONNABORTED"===t||"ETIMEDOUT"===t?{code:TIMEOUT_CODE,message:TIMEOUT_MESSAGE,offline:!0,traceId:E,diagnostic:s}:"RequestOfflineError"===r?{code:OFFLINE_CODE,message:OFFLINE_MESSAGE,offline:!0,traceId:E,diagnostic:s}:"ERR_NETWORK"===t||"Network Error"===s||"Network request failed"===s?{code:NETWORK_CODE,message:UNREACHABLE_MESSAGE,offline:!0,traceId:E,diagnostic:s}:{message:UNEXPECTED_MESSAGE,traceId:E,diagnostic:s})};function extractApiError(e){if(isApiError(e))return e;if("string"==typeof e)return build({message:userSafe(e)??UNEXPECTED_MESSAGE,diagnostic:e||null});if(!isDict(e))return build({message:UNEXPECTED_MESSAGE,diagnostic:null==e?null:String(e)});if(!0===e.isContractError)return build({code:CONTRACT_ERROR_CODE,message:userSafe(e.message)??UNEXPECTED_MESSAGE,diagnostic:nonEmptyString(e.message)});const t=isDict(e.response)?e.response:null,r="number"==typeof t?.status?t.status:"number"==typeof e.status?e.status:0,s=t?t.data:e.body;if(0===r&&null==s)return fromNoResponse(e);const E=isDict(s)?s:null,{fields:n,form:o}=readErrors(E?.errors),i=nonEmptyString(E?.code),a=nonEmptyString(E?.traceId)??requestTraceId(e),l=nonEmptyString(E?.detail)??nonEmptyString(E?.title)??nonEmptyString(s)??nonEmptyString(e.message);let c;if(r>=500){c=(null!==i&&i!==INTERNAL_ERROR_CODE?userSafe(E?.detail):null)??SERVER_FAILURE_MESSAGE}else c=fleetDefaultRefusalSentence(r,E)??userSafe(Object.values(n)[0])??userSafe(o)??userSafe(E?.detail)??userSafe(E?.title)??userSafe(s)??(r?requestFailedMessage(r):UNEXPECTED_MESSAGE);return build({code:i,message:c,fieldErrors:n,status:r,traceId:a,diagnostic:l})}const isNoResponse=e=>extractApiError(e).offline;function apiErrorMessage(e,t){const r=extractApiError(e);if(r.offline||null!==t&&!t)return r.message;return r.message===SERVER_FAILURE_MESSAGE||r.code===REQUEST_CANCELED_CODE||r.message===UNEXPECTED_MESSAGE||r.message===requestFailedMessage(r.status)?t??null:r.message}exports.isNoResponse=isNoResponse;
|
package/lib/commonjs/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ACCESS_TOKEN_KEY",{enumerable:!0,get:function(){return _authStore.ACCESS_TOKEN_KEY}}),Object.defineProperty(exports,"ACCOUNT_ID_HEADER",{enumerable:!0,get:function(){return _clientHeaders.ACCOUNT_ID_HEADER}}),Object.defineProperty(exports,"AsYouType",{enumerable:!0,get:function(){return _index4.AsYouType}}),Object.defineProperty(exports,"CLIENT_BUILD_HEADER",{enumerable:!0,get:function(){return _clientHeaders.CLIENT_BUILD_HEADER}}),Object.defineProperty(exports,"CLIENT_KIND",{enumerable:!0,get:function(){return _clientHeaders.CLIENT_KIND}}),Object.defineProperty(exports,"CLIENT_KIND_HEADER",{enumerable:!0,get:function(){return _clientHeaders.CLIENT_KIND_HEADER}}),Object.defineProperty(exports,"CONTRACT_ERROR_CODE",{enumerable:!0,get:function(){return _index3.CONTRACT_ERROR_CODE}}),Object.defineProperty(exports,"DeepLink",{enumerable:!0,get:function(){return _index2.DeepLink}}),Object.defineProperty(exports,"ENVIRONMENT_APP_ID_SUFFIX",{enumerable:!0,get:function(){return _appIdentity.ENVIRONMENT_APP_ID_SUFFIX}}),Object.defineProperty(exports,"IDEMPOTENCY_KEY_HEADER",{enumerable:!0,get:function(){return _retry.IDEMPOTENCY_KEY_HEADER}}),Object.defineProperty(exports,"LEGACY_REFRESH_TOKEN_LIFETIME_MS",{enumerable:!0,get:function(){return _authStore.LEGACY_REFRESH_TOKEN_LIFETIME_MS}}),Object.defineProperty(exports,"Logger",{enumerable:!0,get:function(){return _index5.Logger}}),Object.defineProperty(exports,"MIN_APP_VERSION_HEADER",{enumerable:!0,get:function(){return _minAppVersion.MIN_APP_VERSION_HEADER}}),Object.defineProperty(exports,"NETWORK_CODE",{enumerable:!0,get:function(){return _index3.NETWORK_CODE}}),Object.defineProperty(exports,"OFFLINE_CODE",{enumerable:!0,get:function(){return _index3.OFFLINE_CODE}}),Object.defineProperty(exports,"OFFLINE_MESSAGE",{enumerable:!0,get:function(){return _index3.OFFLINE_MESSAGE}}),Object.defineProperty(exports,"PUSH_STATUS",{enumerable:!0,get:function(){return _status.PUSH_STATUS}}),Object.defineProperty(exports,"REFRESH_TOKEN_KEY",{enumerable:!0,get:function(){return _authStore.REFRESH_TOKEN_KEY}}),Object.defineProperty(exports,"REQUEST_CANCELED_CODE",{enumerable:!0,get:function(){return _index3.REQUEST_CANCELED_CODE}}),Object.defineProperty(exports,"RequestOfflineError",{enumerable:!0,get:function(){return _userClient.RequestOfflineError}}),Object.defineProperty(exports,"SERVER_FAILURE_MESSAGE",{enumerable:!0,get:function(){return _index3.SERVER_FAILURE_MESSAGE}}),Object.defineProperty(exports,"SESSION_EXPIRED_CODE",{enumerable:!0,get:function(){return _userClient.SESSION_EXPIRED_CODE}}),Object.defineProperty(exports,"SESSION_REVOKED_CODE",{enumerable:!0,get:function(){return _userClient.SESSION_REVOKED_CODE}}),Object.defineProperty(exports,"SESSION_USER_KEY",{enumerable:!0,get:function(){return _authStore.SESSION_USER_KEY}}),Object.defineProperty(exports,"Storage",{enumerable:!0,get:function(){return _index7.Storage}}),Object.defineProperty(exports,"TIMEOUT_CODE",{enumerable:!0,get:function(){return _index3.TIMEOUT_CODE}}),Object.defineProperty(exports,"TIMEOUT_MESSAGE",{enumerable:!0,get:function(){return _index3.TIMEOUT_MESSAGE}}),Object.defineProperty(exports,"TRACEPARENT_HEADER",{enumerable:!0,get:function(){return _requestDefaults.TRACEPARENT_HEADER}}),Object.defineProperty(exports,"UNEXPECTED_MESSAGE",{enumerable:!0,get:function(){return _index3.UNEXPECTED_MESSAGE}}),Object.defineProperty(exports,"UNREACHABLE_MESSAGE",{enumerable:!0,get:function(){return _index3.UNREACHABLE_MESSAGE}}),Object.defineProperty(exports,"VersionCheck",{enumerable:!0,get:function(){return _index9.VersionCheck}}),Object.defineProperty(exports,"WORKSPACE_CHANGED_CODE",{enumerable:!0,get:function(){return _workspace.WORKSPACE_CHANGED_CODE}}),Object.defineProperty(exports,"WorkspaceChangedError",{enumerable:!0,get:function(){return _workspace.WorkspaceChangedError}}),Object.defineProperty(exports,"addDays",{enumerable:!0,get:function(){return _index4.addDays}}),Object.defineProperty(exports,"addMinAppVersionListener",{enumerable:!0,get:function(){return _minAppVersion.addMinAppVersionListener}}),Object.defineProperty(exports,"addNetworkStatusListener",{enumerable:!0,get:function(){return _index6.addNetworkStatusListener}}),Object.defineProperty(exports,"addSessionEndedListener",{enumerable:!0,get:function(){return _authStore.addSessionEndedListener}}),Object.defineProperty(exports,"apiErrorMessage",{enumerable:!0,get:function(){return _index3.apiErrorMessage}}),Object.defineProperty(exports,"applyRequestDefaults",{enumerable:!0,get:function(){return _requestDefaults.applyRequestDefaults}}),Object.defineProperty(exports,"attachRetry",{enumerable:!0,get:function(){return _retry.attachRetry}}),Object.defineProperty(exports,"buildCurl",{enumerable:!0,get:function(){return _curl.buildCurl}}),Object.defineProperty(exports,"clampNationalNumber",{enumerable:!0,get:function(){return _index4.clampNationalNumber}}),Object.defineProperty(exports,"clearSession",{enumerable:!0,get:function(){return _authStore.clearSession}}),Object.defineProperty(exports,"configureFormatters",{enumerable:!0,get:function(){return _index4.configureFormatters}}),Object.defineProperty(exports,"configureLogger",{enumerable:!0,get:function(){return _index5.configureLogger}}),Object.defineProperty(exports,"countryFlagEmoji",{enumerable:!0,get:function(){return _index4.countryFlagEmoji}}),Object.defineProperty(exports,"crashlyticsRemoteLogger",{enumerable:!0,get:function(){return _crashlytics.crashlyticsRemoteLogger}}),Object.defineProperty(exports,"decodeJWT",{enumerable:!0,get:function(){return _jwt.decodeJWT}}),Object.defineProperty(exports,"detectPhoneCountry",{enumerable:!0,get:function(){return _index4.detectPhoneCountry}}),Object.defineProperty(exports,"diffMs",{enumerable:!0,get:function(){return _index4.diffMs}}),Object.defineProperty(exports,"encodeBase64",{enumerable:!0,get:function(){return _base.encodeBase64}}),Object.defineProperty(exports,"extractApiError",{enumerable:!0,get:function(){return _index3.extractApiError}}),Object.defineProperty(exports,"formatCompactNumber",{enumerable:!0,get:function(){return _index4.formatCompactNumber}}),Object.defineProperty(exports,"formatCurrency",{enumerable:!0,get:function(){return _index4.formatCurrency}}),Object.defineProperty(exports,"formatDate",{enumerable:!0,get:function(){return _index4.formatDate}}),Object.defineProperty(exports,"formatDateDDMMMYYYY",{enumerable:!0,get:function(){return _index4.formatDateDDMMMYYYY}}),Object.defineProperty(exports,"formatDateISO",{enumerable:!0,get:function(){return _index4.formatDateISO}}),Object.defineProperty(exports,"formatDatePattern",{enumerable:!0,get:function(){return _index4.formatDatePattern}}),Object.defineProperty(exports,"formatDateTime",{enumerable:!0,get:function(){return _index4.formatDateTime}}),Object.defineProperty(exports,"formatMinor",{enumerable:!0,get:function(){return _index4.formatMinor}}),Object.defineProperty(exports,"formatNumber",{enumerable:!0,get:function(){return _index4.formatNumber}}),Object.defineProperty(exports,"formatPercent",{enumerable:!0,get:function(){return _index4.formatPercent}}),Object.defineProperty(exports,"formatPhone",{enumerable:!0,get:function(){return _index4.formatPhone}}),Object.defineProperty(exports,"formatPhoneAsTyped",{enumerable:!0,get:function(){return _index4.formatPhoneAsTyped}}),Object.defineProperty(exports,"formatRelative",{enumerable:!0,get:function(){return _index4.formatRelative}}),Object.defineProperty(exports,"formatRelativeTime",{enumerable:!0,get:function(){return _index4.formatRelativeTime}}),Object.defineProperty(exports,"formatTime",{enumerable:!0,get:function(){return _index4.formatTime}}),Object.defineProperty(exports,"formatTime12h",{enumerable:!0,get:function(){return _index4.formatTime12h}}),Object.defineProperty(exports,"formatTimeInWindowsZone",{enumerable:!0,get:function(){return _index4.formatTimeInWindowsZone}}),Object.defineProperty(exports,"formatTimeInZone",{enumerable:!0,get:function(){return _index4.formatTimeInZone}}),Object.defineProperty(exports,"getClientBuild",{enumerable:!0,get:function(){return _clientHeaders.getClientBuild}}),Object.defineProperty(exports,"getConfig",{enumerable:!0,get:function(){return _index.getConfig}}),Object.defineProperty(exports,"getConfigValue",{enumerable:!0,get:function(){return _index.getConfigValue}}),Object.defineProperty(exports,"getCountries",{enumerable:!0,get:function(){return _index4.getCountries}}),Object.defineProperty(exports,"getCountryCallingCode",{enumerable:!0,get:function(){return _index4.getCountryCallingCode}}),Object.defineProperty(exports,"getDeviceContext",{enumerable:!0,get:function(){return _index5.getDeviceContext}}),Object.defineProperty(exports,"getFormatterConfig",{enumerable:!0,get:function(){return _index4.getFormatterConfig}}),Object.defineProperty(exports,"getInitials",{enumerable:!0,get:function(){return _index4.getInitials}}),Object.defineProperty(exports,"getJWTExpiry",{enumerable:!0,get:function(){return _jwt.getJWTExpiry}}),Object.defineProperty(exports,"getMinAppVersion",{enumerable:!0,get:function(){return _minAppVersion.getMinAppVersion}}),Object.defineProperty(exports,"getNetworkStatus",{enumerable:!0,get:function(){return _index6.getNetworkStatus}}),Object.defineProperty(exports,"getPhoneCountries",{enumerable:!0,get:function(){return _index4.getPhoneCountries}}),Object.defineProperty(exports,"getSessionUser",{enumerable:!0,get:function(){return _authStore.getSessionUser}}),Object.defineProperty(exports,"getToken",{enumerable:!0,get:function(){return _authStore.getToken}}),Object.defineProperty(exports,"groupingForLocale",{enumerable:!0,get:function(){return _index4.groupingForLocale}}),Object.defineProperty(exports,"initUserAuth",{enumerable:!0,get:function(){return _initUserAuth.initUserAuth}}),Object.defineProperty(exports,"initWebority",{enumerable:!0,get:function(){return _initSDK.initWebority}}),Object.defineProperty(exports,"injectStore",{enumerable:!0,get:function(){return _userClient.injectStore}}),Object.defineProperty(exports,"injectUserAuth",{enumerable:!0,get:function(){return _userClient.injectUserAuth}}),Object.defineProperty(exports,"installedAppId",{enumerable:!0,get:function(){return _appIdentity.installedAppId}}),Object.defineProperty(exports,"isAadhaar",{enumerable:!0,get:function(){return _index8.isAadhaar}}),Object.defineProperty(exports,"isAlphanumeric",{enumerable:!0,get:function(){return _index8.isAlphanumeric}}),Object.defineProperty(exports,"isApiError",{enumerable:!0,get:function(){return _index3.isApiError}}),Object.defineProperty(exports,"isBetween",{enumerable:!0,get:function(){return _index8.isBetween}}),Object.defineProperty(exports,"isBuildBelowMinimum",{enumerable:!0,get:function(){return _index9.isBuildBelowMinimum}}),Object.defineProperty(exports,"isDateAfter",{enumerable:!0,get:function(){return _index4.isDateAfter}}),Object.defineProperty(exports,"isDateBefore",{enumerable:!0,get:function(){return _index4.isDateBefore}}),Object.defineProperty(exports,"isEmail",{enumerable:!0,get:function(){return _index8.isEmail}}),Object.defineProperty(exports,"isGstin",{enumerable:!0,get:function(){return _index8.isGstin}}),Object.defineProperty(exports,"isHexColor",{enumerable:!0,get:function(){return _index8.isHexColor}}),Object.defineProperty(exports,"isIfsc",{enumerable:!0,get:function(){return _index8.isIfsc}}),Object.defineProperty(exports,"isIndianMobile",{enumerable:!0,get:function(){return _index8.isIndianMobile}}),Object.defineProperty(exports,"isIndianPincode",{enumerable:!0,get:function(){return _index8.isIndianPincode}}),Object.defineProperty(exports,"isInteger",{enumerable:!0,get:function(){return _index8.isInteger}}),Object.defineProperty(exports,"isJWTExpired",{enumerable:!0,get:function(){return _jwt.isJWTExpired}}),Object.defineProperty(exports,"isNeverSentError",{enumerable:!0,get:function(){return _retry.isNeverSentError}}),Object.defineProperty(exports,"isNoResponse",{enumerable:!0,get:function(){return _index3.isNoResponse}}),Object.defineProperty(exports,"isNonEmpty",{enumerable:!0,get:function(){return _index8.isNonEmpty}}),Object.defineProperty(exports,"isNumeric",{enumerable:!0,get:function(){return _index8.isNumeric}}),Object.defineProperty(exports,"isPan",{enumerable:!0,get:function(){return _index8.isPan}}),Object.defineProperty(exports,"isPhone",{enumerable:!0,get:function(){return _index8.isPhone}}),Object.defineProperty(exports,"isRetryableFailure",{enumerable:!0,get:function(){return _retry.isRetryableFailure}}),Object.defineProperty(exports,"isRetryableStatus",{enumerable:!0,get:function(){return _retry.isRetryableStatus}}),Object.defineProperty(exports,"isSameDay",{enumerable:!0,get:function(){return _index4.isSameDay}}),Object.defineProperty(exports,"isStorageAvailable",{enumerable:!0,get:function(){return _index7.isStorageAvailable}}),Object.defineProperty(exports,"isStrongPassword",{enumerable:!0,get:function(){return _index8.isStrongPassword}}),Object.defineProperty(exports,"isSupportedCountry",{enumerable:!0,get:function(){return _index4.isSupportedCountry}}),Object.defineProperty(exports,"isUrl",{enumerable:!0,get:function(){return _index8.isUrl}}),Object.defineProperty(exports,"isValidNationalNumber",{enumerable:!0,get:function(){return _index4.isValidNationalNumber}}),Object.defineProperty(exports,"isValidPhoneNumber",{enumerable:!0,get:function(){return _index4.isValidPhoneNumber}}),Object.defineProperty(exports,"isWorkspaceChangedError",{enumerable:!0,get:function(){return _workspace.isWorkspaceChangedError}}),Object.defineProperty(exports,"logCurl",{enumerable:!0,get:function(){return _curl.logCurl}}),Object.defineProperty(exports,"maxLength",{enumerable:!0,get:function(){return _index8.maxLength}}),Object.defineProperty(exports,"maxNationalNumberLength",{enumerable:!0,get:function(){return _index4.maxNationalNumberLength}}),Object.defineProperty(exports,"minLength",{enumerable:!0,get:function(){return _index8.minLength}}),Object.defineProperty(exports,"newTraceparent",{enumerable:!0,get:function(){return _requestDefaults.newTraceparent}}),Object.defineProperty(exports,"normalizePhone",{enumerable:!0,get:function(){return _index4.normalizePhone}}),Object.defineProperty(exports,"parseBuildNumber",{enumerable:!0,get:function(){return _index9.parseBuildNumber}}),Object.defineProperty(exports,"parseDeepLink",{enumerable:!0,get:function(){return _index2.parseDeepLink}}),Object.defineProperty(exports,"parsePhoneNumber",{enumerable:!0,get:function(){return _index4.parsePhoneNumber}}),Object.defineProperty(exports,"parsePhoneNumberFromString",{enumerable:!0,get:function(){return _index4.parsePhoneNumberFromString}}),Object.defineProperty(exports,"publicClient",{enumerable:!0,get:function(){return _publicClient.default}}),Object.defineProperty(exports,"refreshAccessToken",{enumerable:!0,get:function(){return _tokenRefresh.refreshAccessToken}}),Object.defineProperty(exports,"removeSessionUser",{enumerable:!0,get:function(){return _authStore.removeSessionUser}}),Object.defineProperty(exports,"removeToken",{enumerable:!0,get:function(){return _authStore.removeToken}}),Object.defineProperty(exports,"resendWhenUnanswered",{enumerable:!0,get:function(){return _retry.resendWhenUnanswered}}),Object.defineProperty(exports,"resetConfig",{enumerable:!0,get:function(){return _index.resetConfig}}),Object.defineProperty(exports,"resetRefreshState",{enumerable:!0,get:function(){return _userClient.resetRefreshState}}),Object.defineProperty(exports,"retryAfterMs",{enumerable:!0,get:function(){return _retry.retryAfterMs}}),Object.defineProperty(exports,"setConfig",{enumerable:!0,get:function(){return _index.setConfig}}),Object.defineProperty(exports,"setDeviceContext",{enumerable:!0,get:function(){return _index5.setDeviceContext}}),Object.defineProperty(exports,"setDeviceInfoImplementation",{enumerable:!0,get:function(){return _index9.setDeviceInfoImplementation}}),Object.defineProperty(exports,"setKeychainImplementation",{enumerable:!0,get:function(){return _authStore.setKeychainImplementation}}),Object.defineProperty(exports,"setLegacyTokenKeys",{enumerable:!0,get:function(){return _authStore.setLegacyTokenKeys}}),Object.defineProperty(exports,"setNetworkStatusImplementation",{enumerable:!0,get:function(){return _index6.setNetworkStatusImplementation}}),Object.defineProperty(exports,"setStorageImplementation",{enumerable:!0,get:function(){return _index7.setStorageImplementation}}),Object.defineProperty(exports,"splitPhoneNumber",{enumerable:!0,get:function(){return _index4.splitPhoneNumber}}),Object.defineProperty(exports,"startOfDay",{enumerable:!0,get:function(){return _index4.startOfDay}}),Object.defineProperty(exports,"storeSessionUser",{enumerable:!0,get:function(){return _authStore.storeSessionUser}}),Object.defineProperty(exports,"storeToken",{enumerable:!0,get:function(){return _authStore.storeToken}}),Object.defineProperty(exports,"toFieldPath",{enumerable:!0,get:function(){return _index3.toFieldPath}}),Object.defineProperty(exports,"useDeepLink",{enumerable:!0,get:function(){return _index2.useDeepLink}}),Object.defineProperty(exports,"useNetworkStatus",{enumerable:!0,get:function(){return _index6.useNetworkStatus}}),Object.defineProperty(exports,"useVersionCheck",{enumerable:!0,get:function(){return _index9.useVersionCheck}}),Object.defineProperty(exports,"userClient",{enumerable:!0,get:function(){return _userClient.default}}),Object.defineProperty(exports,"validatePhoneNumberLength",{enumerable:!0,get:function(){return _index4.validatePhoneNumberLength}});var cache,_clientHeaders=require("./api/clientHeaders.js"),_curl=require("./api/curl.js"),_minAppVersion=require("./api/minAppVersion.js"),_publicClient=_interopRequireDefault(require("./api/publicClient.js")),_requestDefaults=require("./api/requestDefaults.js"),_retry=require("./api/retry.js"),_tokenRefresh=require("./api/tokenRefresh.js"),_userClient=_interopRequireWildcard(require("./api/userClient.js")),_workspace=require("./api/workspace.js"),_authStore=require("./auth/authStore.js"),_jwt=require("./auth/jwt.js"),_index=require("./config/index.js"),_appIdentity=require("./config/appIdentity.js"),_index2=require("./deepLink/index.js"),_index3=require("./errors/index.js"),_index4=require("./formatters/index.js"),_initSDK=require("./initSDK.js"),_initUserAuth=require("./initUserAuth.js"),_index5=require("./logger/index.js"),_crashlytics=require("./logger/crashlytics.js"),_index6=require("./network/index.js"),_status=require("./push/status.js"),_index7=require("./storage/index.js"),_base=require("./utils/base64.js"),_index8=require("./validators/index.js"),_index9=require("./versionCheck/index.js");function _interopRequireWildcard(e,r){if(!r&&e&&e.__esModule)return e;var t,n,i=Object.defineProperty,o={__proto__:null,default:e};if(Object(e)!==e)return o;if(cache||"function"!=typeof WeakMap||(cache=new WeakMap),cache){if(cache.has(e))return cache.get(e);cache.set(e,o)}for(n in e)"default"!==n&&{}.hasOwnProperty.call(e,n)&&((t=i&&Object.getOwnPropertyDescriptor(e,n))&&(t.get||t.set)?i(o,n,t):o[n]=e[n]);return o}function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ACCESS_TOKEN_KEY",{enumerable:!0,get:function(){return _authStore.ACCESS_TOKEN_KEY}}),Object.defineProperty(exports,"ACCOUNT_ID_HEADER",{enumerable:!0,get:function(){return _clientHeaders.ACCOUNT_ID_HEADER}}),Object.defineProperty(exports,"AsYouType",{enumerable:!0,get:function(){return _index4.AsYouType}}),Object.defineProperty(exports,"CLIENT_BUILD_HEADER",{enumerable:!0,get:function(){return _clientHeaders.CLIENT_BUILD_HEADER}}),Object.defineProperty(exports,"CLIENT_KIND",{enumerable:!0,get:function(){return _clientHeaders.CLIENT_KIND}}),Object.defineProperty(exports,"CLIENT_KIND_HEADER",{enumerable:!0,get:function(){return _clientHeaders.CLIENT_KIND_HEADER}}),Object.defineProperty(exports,"CONTRACT_ERROR_CODE",{enumerable:!0,get:function(){return _index3.CONTRACT_ERROR_CODE}}),Object.defineProperty(exports,"DeepLink",{enumerable:!0,get:function(){return _index2.DeepLink}}),Object.defineProperty(exports,"ENVIRONMENT_APP_ID_SUFFIX",{enumerable:!0,get:function(){return _appIdentity.ENVIRONMENT_APP_ID_SUFFIX}}),Object.defineProperty(exports,"IDEMPOTENCY_KEY_HEADER",{enumerable:!0,get:function(){return _retry.IDEMPOTENCY_KEY_HEADER}}),Object.defineProperty(exports,"LEGACY_REFRESH_TOKEN_LIFETIME_MS",{enumerable:!0,get:function(){return _authStore.LEGACY_REFRESH_TOKEN_LIFETIME_MS}}),Object.defineProperty(exports,"Logger",{enumerable:!0,get:function(){return _index5.Logger}}),Object.defineProperty(exports,"MIN_APP_VERSION_HEADER",{enumerable:!0,get:function(){return _minAppVersion.MIN_APP_VERSION_HEADER}}),Object.defineProperty(exports,"NETWORK_CODE",{enumerable:!0,get:function(){return _index3.NETWORK_CODE}}),Object.defineProperty(exports,"OFFLINE_CODE",{enumerable:!0,get:function(){return _index3.OFFLINE_CODE}}),Object.defineProperty(exports,"OFFLINE_MESSAGE",{enumerable:!0,get:function(){return _index3.OFFLINE_MESSAGE}}),Object.defineProperty(exports,"PUSH_STATUS",{enumerable:!0,get:function(){return _status.PUSH_STATUS}}),Object.defineProperty(exports,"REFRESH_TOKEN_KEY",{enumerable:!0,get:function(){return _authStore.REFRESH_TOKEN_KEY}}),Object.defineProperty(exports,"REQUEST_CANCELED_CODE",{enumerable:!0,get:function(){return _index3.REQUEST_CANCELED_CODE}}),Object.defineProperty(exports,"RequestOfflineError",{enumerable:!0,get:function(){return _userClient.RequestOfflineError}}),Object.defineProperty(exports,"SERVER_FAILURE_MESSAGE",{enumerable:!0,get:function(){return _index3.SERVER_FAILURE_MESSAGE}}),Object.defineProperty(exports,"SESSION_EXPIRED_CODE",{enumerable:!0,get:function(){return _userClient.SESSION_EXPIRED_CODE}}),Object.defineProperty(exports,"SESSION_REVOKED_CODE",{enumerable:!0,get:function(){return _userClient.SESSION_REVOKED_CODE}}),Object.defineProperty(exports,"SESSION_USER_KEY",{enumerable:!0,get:function(){return _authStore.SESSION_USER_KEY}}),Object.defineProperty(exports,"Storage",{enumerable:!0,get:function(){return _index7.Storage}}),Object.defineProperty(exports,"TIMEOUT_CODE",{enumerable:!0,get:function(){return _index3.TIMEOUT_CODE}}),Object.defineProperty(exports,"TIMEOUT_MESSAGE",{enumerable:!0,get:function(){return _index3.TIMEOUT_MESSAGE}}),Object.defineProperty(exports,"TRACEPARENT_HEADER",{enumerable:!0,get:function(){return _requestDefaults.TRACEPARENT_HEADER}}),Object.defineProperty(exports,"UNEXPECTED_MESSAGE",{enumerable:!0,get:function(){return _index3.UNEXPECTED_MESSAGE}}),Object.defineProperty(exports,"UNREACHABLE_MESSAGE",{enumerable:!0,get:function(){return _index3.UNREACHABLE_MESSAGE}}),Object.defineProperty(exports,"VersionCheck",{enumerable:!0,get:function(){return _index9.VersionCheck}}),Object.defineProperty(exports,"WORKSPACE_CHANGED_CODE",{enumerable:!0,get:function(){return _workspace.WORKSPACE_CHANGED_CODE}}),Object.defineProperty(exports,"WorkspaceChangedError",{enumerable:!0,get:function(){return _workspace.WorkspaceChangedError}}),Object.defineProperty(exports,"addDays",{enumerable:!0,get:function(){return _index4.addDays}}),Object.defineProperty(exports,"addMinAppVersionListener",{enumerable:!0,get:function(){return _minAppVersion.addMinAppVersionListener}}),Object.defineProperty(exports,"addNetworkStatusListener",{enumerable:!0,get:function(){return _index6.addNetworkStatusListener}}),Object.defineProperty(exports,"addSessionEndedListener",{enumerable:!0,get:function(){return _authStore.addSessionEndedListener}}),Object.defineProperty(exports,"apiErrorMessage",{enumerable:!0,get:function(){return _index3.apiErrorMessage}}),Object.defineProperty(exports,"applyRequestDefaults",{enumerable:!0,get:function(){return _requestDefaults.applyRequestDefaults}}),Object.defineProperty(exports,"attachRetry",{enumerable:!0,get:function(){return _retry.attachRetry}}),Object.defineProperty(exports,"buildCurl",{enumerable:!0,get:function(){return _curl.buildCurl}}),Object.defineProperty(exports,"clampNationalNumber",{enumerable:!0,get:function(){return _index4.clampNationalNumber}}),Object.defineProperty(exports,"clearSession",{enumerable:!0,get:function(){return _authStore.clearSession}}),Object.defineProperty(exports,"configureFormatters",{enumerable:!0,get:function(){return _index4.configureFormatters}}),Object.defineProperty(exports,"configureLogger",{enumerable:!0,get:function(){return _index5.configureLogger}}),Object.defineProperty(exports,"countryFlagEmoji",{enumerable:!0,get:function(){return _index4.countryFlagEmoji}}),Object.defineProperty(exports,"crashlyticsRemoteLogger",{enumerable:!0,get:function(){return _crashlytics.crashlyticsRemoteLogger}}),Object.defineProperty(exports,"decodeJWT",{enumerable:!0,get:function(){return _jwt.decodeJWT}}),Object.defineProperty(exports,"detectPhoneCountry",{enumerable:!0,get:function(){return _index4.detectPhoneCountry}}),Object.defineProperty(exports,"diffMs",{enumerable:!0,get:function(){return _index4.diffMs}}),Object.defineProperty(exports,"encodeBase64",{enumerable:!0,get:function(){return _base.encodeBase64}}),Object.defineProperty(exports,"extractApiError",{enumerable:!0,get:function(){return _index3.extractApiError}}),Object.defineProperty(exports,"formatCompactNumber",{enumerable:!0,get:function(){return _index4.formatCompactNumber}}),Object.defineProperty(exports,"formatCurrency",{enumerable:!0,get:function(){return _index4.formatCurrency}}),Object.defineProperty(exports,"formatDate",{enumerable:!0,get:function(){return _index4.formatDate}}),Object.defineProperty(exports,"formatDateDDMMMYYYY",{enumerable:!0,get:function(){return _index4.formatDateDDMMMYYYY}}),Object.defineProperty(exports,"formatDateISO",{enumerable:!0,get:function(){return _index4.formatDateISO}}),Object.defineProperty(exports,"formatDatePattern",{enumerable:!0,get:function(){return _index4.formatDatePattern}}),Object.defineProperty(exports,"formatDateTime",{enumerable:!0,get:function(){return _index4.formatDateTime}}),Object.defineProperty(exports,"formatMinor",{enumerable:!0,get:function(){return _index4.formatMinor}}),Object.defineProperty(exports,"formatNumber",{enumerable:!0,get:function(){return _index4.formatNumber}}),Object.defineProperty(exports,"formatPercent",{enumerable:!0,get:function(){return _index4.formatPercent}}),Object.defineProperty(exports,"formatPhone",{enumerable:!0,get:function(){return _index4.formatPhone}}),Object.defineProperty(exports,"formatPhoneAsTyped",{enumerable:!0,get:function(){return _index4.formatPhoneAsTyped}}),Object.defineProperty(exports,"formatRelative",{enumerable:!0,get:function(){return _index4.formatRelative}}),Object.defineProperty(exports,"formatRelativeTime",{enumerable:!0,get:function(){return _index4.formatRelativeTime}}),Object.defineProperty(exports,"formatTime",{enumerable:!0,get:function(){return _index4.formatTime}}),Object.defineProperty(exports,"formatTime12h",{enumerable:!0,get:function(){return _index4.formatTime12h}}),Object.defineProperty(exports,"formatTimeInWindowsZone",{enumerable:!0,get:function(){return _index4.formatTimeInWindowsZone}}),Object.defineProperty(exports,"formatTimeInZone",{enumerable:!0,get:function(){return _index4.formatTimeInZone}}),Object.defineProperty(exports,"getClientBuild",{enumerable:!0,get:function(){return _clientHeaders.getClientBuild}}),Object.defineProperty(exports,"getConfig",{enumerable:!0,get:function(){return _index.getConfig}}),Object.defineProperty(exports,"getConfigValue",{enumerable:!0,get:function(){return _index.getConfigValue}}),Object.defineProperty(exports,"getCountries",{enumerable:!0,get:function(){return _index4.getCountries}}),Object.defineProperty(exports,"getCountryCallingCode",{enumerable:!0,get:function(){return _index4.getCountryCallingCode}}),Object.defineProperty(exports,"getDeviceContext",{enumerable:!0,get:function(){return _index5.getDeviceContext}}),Object.defineProperty(exports,"getFormatterConfig",{enumerable:!0,get:function(){return _index4.getFormatterConfig}}),Object.defineProperty(exports,"getInitials",{enumerable:!0,get:function(){return _index4.getInitials}}),Object.defineProperty(exports,"getJWTExpiry",{enumerable:!0,get:function(){return _jwt.getJWTExpiry}}),Object.defineProperty(exports,"getMinAppVersion",{enumerable:!0,get:function(){return _minAppVersion.getMinAppVersion}}),Object.defineProperty(exports,"getNetworkStatus",{enumerable:!0,get:function(){return _index6.getNetworkStatus}}),Object.defineProperty(exports,"getPhoneCountries",{enumerable:!0,get:function(){return _index4.getPhoneCountries}}),Object.defineProperty(exports,"getSessionUser",{enumerable:!0,get:function(){return _authStore.getSessionUser}}),Object.defineProperty(exports,"getToken",{enumerable:!0,get:function(){return _authStore.getToken}}),Object.defineProperty(exports,"groupingForLocale",{enumerable:!0,get:function(){return _index4.groupingForLocale}}),Object.defineProperty(exports,"initUserAuth",{enumerable:!0,get:function(){return _initUserAuth.initUserAuth}}),Object.defineProperty(exports,"initWebority",{enumerable:!0,get:function(){return _initSDK.initWebority}}),Object.defineProperty(exports,"injectStore",{enumerable:!0,get:function(){return _userClient.injectStore}}),Object.defineProperty(exports,"injectUserAuth",{enumerable:!0,get:function(){return _userClient.injectUserAuth}}),Object.defineProperty(exports,"installedAppId",{enumerable:!0,get:function(){return _appIdentity.installedAppId}}),Object.defineProperty(exports,"isAadhaar",{enumerable:!0,get:function(){return _index8.isAadhaar}}),Object.defineProperty(exports,"isAlphanumeric",{enumerable:!0,get:function(){return _index8.isAlphanumeric}}),Object.defineProperty(exports,"isApiError",{enumerable:!0,get:function(){return _index3.isApiError}}),Object.defineProperty(exports,"isBetween",{enumerable:!0,get:function(){return _index8.isBetween}}),Object.defineProperty(exports,"isBuildBelowMinimum",{enumerable:!0,get:function(){return _index9.isBuildBelowMinimum}}),Object.defineProperty(exports,"isDateAfter",{enumerable:!0,get:function(){return _index4.isDateAfter}}),Object.defineProperty(exports,"isDateBefore",{enumerable:!0,get:function(){return _index4.isDateBefore}}),Object.defineProperty(exports,"isEmail",{enumerable:!0,get:function(){return _index8.isEmail}}),Object.defineProperty(exports,"isGstin",{enumerable:!0,get:function(){return _index8.isGstin}}),Object.defineProperty(exports,"isHexColor",{enumerable:!0,get:function(){return _index8.isHexColor}}),Object.defineProperty(exports,"isIfsc",{enumerable:!0,get:function(){return _index8.isIfsc}}),Object.defineProperty(exports,"isIndianMobile",{enumerable:!0,get:function(){return _index8.isIndianMobile}}),Object.defineProperty(exports,"isIndianPincode",{enumerable:!0,get:function(){return _index8.isIndianPincode}}),Object.defineProperty(exports,"isInteger",{enumerable:!0,get:function(){return _index8.isInteger}}),Object.defineProperty(exports,"isJWTExpired",{enumerable:!0,get:function(){return _jwt.isJWTExpired}}),Object.defineProperty(exports,"isNeverSentError",{enumerable:!0,get:function(){return _retry.isNeverSentError}}),Object.defineProperty(exports,"isNoResponse",{enumerable:!0,get:function(){return _index3.isNoResponse}}),Object.defineProperty(exports,"isNonEmpty",{enumerable:!0,get:function(){return _index8.isNonEmpty}}),Object.defineProperty(exports,"isNumeric",{enumerable:!0,get:function(){return _index8.isNumeric}}),Object.defineProperty(exports,"isPan",{enumerable:!0,get:function(){return _index8.isPan}}),Object.defineProperty(exports,"isPhone",{enumerable:!0,get:function(){return _index8.isPhone}}),Object.defineProperty(exports,"isRetryableFailure",{enumerable:!0,get:function(){return _retry.isRetryableFailure}}),Object.defineProperty(exports,"isRetryableStatus",{enumerable:!0,get:function(){return _retry.isRetryableStatus}}),Object.defineProperty(exports,"isSameDay",{enumerable:!0,get:function(){return _index4.isSameDay}}),Object.defineProperty(exports,"isStorageAvailable",{enumerable:!0,get:function(){return _index7.isStorageAvailable}}),Object.defineProperty(exports,"isStrongPassword",{enumerable:!0,get:function(){return _index8.isStrongPassword}}),Object.defineProperty(exports,"isSupportedCountry",{enumerable:!0,get:function(){return _index4.isSupportedCountry}}),Object.defineProperty(exports,"isUrl",{enumerable:!0,get:function(){return _index8.isUrl}}),Object.defineProperty(exports,"isValidNationalNumber",{enumerable:!0,get:function(){return _index4.isValidNationalNumber}}),Object.defineProperty(exports,"isValidPhoneNumber",{enumerable:!0,get:function(){return _index4.isValidPhoneNumber}}),Object.defineProperty(exports,"isWorkspaceChangedError",{enumerable:!0,get:function(){return _workspace.isWorkspaceChangedError}}),Object.defineProperty(exports,"logCurl",{enumerable:!0,get:function(){return _curl.logCurl}}),Object.defineProperty(exports,"maxLength",{enumerable:!0,get:function(){return _index8.maxLength}}),Object.defineProperty(exports,"maxNationalNumberLength",{enumerable:!0,get:function(){return _index4.maxNationalNumberLength}}),Object.defineProperty(exports,"minLength",{enumerable:!0,get:function(){return _index8.minLength}}),Object.defineProperty(exports,"newIdempotencyKey",{enumerable:!0,get:function(){return _idempotencyKey.newIdempotencyKey}}),Object.defineProperty(exports,"newTraceparent",{enumerable:!0,get:function(){return _requestDefaults.newTraceparent}}),Object.defineProperty(exports,"normalizePhone",{enumerable:!0,get:function(){return _index4.normalizePhone}}),Object.defineProperty(exports,"parseBuildNumber",{enumerable:!0,get:function(){return _index9.parseBuildNumber}}),Object.defineProperty(exports,"parseDeepLink",{enumerable:!0,get:function(){return _index2.parseDeepLink}}),Object.defineProperty(exports,"parsePhoneNumber",{enumerable:!0,get:function(){return _index4.parsePhoneNumber}}),Object.defineProperty(exports,"parsePhoneNumberFromString",{enumerable:!0,get:function(){return _index4.parsePhoneNumberFromString}}),Object.defineProperty(exports,"publicClient",{enumerable:!0,get:function(){return _publicClient.default}}),Object.defineProperty(exports,"refreshAccessToken",{enumerable:!0,get:function(){return _tokenRefresh.refreshAccessToken}}),Object.defineProperty(exports,"removeSessionUser",{enumerable:!0,get:function(){return _authStore.removeSessionUser}}),Object.defineProperty(exports,"removeToken",{enumerable:!0,get:function(){return _authStore.removeToken}}),Object.defineProperty(exports,"resendWhenUnanswered",{enumerable:!0,get:function(){return _retry.resendWhenUnanswered}}),Object.defineProperty(exports,"resetConfig",{enumerable:!0,get:function(){return _index.resetConfig}}),Object.defineProperty(exports,"resetRefreshState",{enumerable:!0,get:function(){return _userClient.resetRefreshState}}),Object.defineProperty(exports,"retryAfterMs",{enumerable:!0,get:function(){return _retry.retryAfterMs}}),Object.defineProperty(exports,"setConfig",{enumerable:!0,get:function(){return _index.setConfig}}),Object.defineProperty(exports,"setDeviceContext",{enumerable:!0,get:function(){return _index5.setDeviceContext}}),Object.defineProperty(exports,"setDeviceInfoImplementation",{enumerable:!0,get:function(){return _index9.setDeviceInfoImplementation}}),Object.defineProperty(exports,"setKeychainImplementation",{enumerable:!0,get:function(){return _authStore.setKeychainImplementation}}),Object.defineProperty(exports,"setLegacyTokenKeys",{enumerable:!0,get:function(){return _authStore.setLegacyTokenKeys}}),Object.defineProperty(exports,"setNetworkStatusImplementation",{enumerable:!0,get:function(){return _index6.setNetworkStatusImplementation}}),Object.defineProperty(exports,"setStorageImplementation",{enumerable:!0,get:function(){return _index7.setStorageImplementation}}),Object.defineProperty(exports,"splitPhoneNumber",{enumerable:!0,get:function(){return _index4.splitPhoneNumber}}),Object.defineProperty(exports,"startOfDay",{enumerable:!0,get:function(){return _index4.startOfDay}}),Object.defineProperty(exports,"storeSessionUser",{enumerable:!0,get:function(){return _authStore.storeSessionUser}}),Object.defineProperty(exports,"storeToken",{enumerable:!0,get:function(){return _authStore.storeToken}}),Object.defineProperty(exports,"toFieldPath",{enumerable:!0,get:function(){return _index3.toFieldPath}}),Object.defineProperty(exports,"useDeepLink",{enumerable:!0,get:function(){return _index2.useDeepLink}}),Object.defineProperty(exports,"useNetworkStatus",{enumerable:!0,get:function(){return _index6.useNetworkStatus}}),Object.defineProperty(exports,"useVersionCheck",{enumerable:!0,get:function(){return _index9.useVersionCheck}}),Object.defineProperty(exports,"userClient",{enumerable:!0,get:function(){return _userClient.default}}),Object.defineProperty(exports,"validatePhoneNumberLength",{enumerable:!0,get:function(){return _index4.validatePhoneNumberLength}});var cache,_clientHeaders=require("./api/clientHeaders.js"),_curl=require("./api/curl.js"),_idempotencyKey=require("./api/idempotencyKey.js"),_minAppVersion=require("./api/minAppVersion.js"),_publicClient=_interopRequireDefault(require("./api/publicClient.js")),_requestDefaults=require("./api/requestDefaults.js"),_retry=require("./api/retry.js"),_tokenRefresh=require("./api/tokenRefresh.js"),_userClient=_interopRequireWildcard(require("./api/userClient.js")),_workspace=require("./api/workspace.js"),_authStore=require("./auth/authStore.js"),_jwt=require("./auth/jwt.js"),_index=require("./config/index.js"),_appIdentity=require("./config/appIdentity.js"),_index2=require("./deepLink/index.js"),_index3=require("./errors/index.js"),_index4=require("./formatters/index.js"),_initSDK=require("./initSDK.js"),_initUserAuth=require("./initUserAuth.js"),_index5=require("./logger/index.js"),_crashlytics=require("./logger/crashlytics.js"),_index6=require("./network/index.js"),_status=require("./push/status.js"),_index7=require("./storage/index.js"),_base=require("./utils/base64.js"),_index8=require("./validators/index.js"),_index9=require("./versionCheck/index.js");function _interopRequireWildcard(e,r){if(!r&&e&&e.__esModule)return e;var t,n,i=Object.defineProperty,o={__proto__:null,default:e};if(Object(e)!==e)return o;if(cache||"function"!=typeof WeakMap||(cache=new WeakMap),cache){if(cache.has(e))return cache.get(e);cache.set(e,o)}for(n in e)"default"!==n&&{}.hasOwnProperty.call(e,n)&&((t=i&&Object.getOwnPropertyDescriptor(e,n))&&(t.get||t.set)?i(o,n,t):o[n]=e[n]);return o}function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.initUserAuth=void 0;var _userClient=require("./api/userClient.js"),_authStore=require("./auth/authStore.js"),_index=require("./logger/index.js");const initUserAuth=(e,r)=>{if(!e)throw new Error("Redux store is required for user package initialization");if(!r.logout||!r.refresh?.path)throw new Error("initUserAuth needs a logout action and refresh.path");(0,_userClient.injectStore)(e),(0,_userClient.injectUserAuth)(r),(0,_authStore.setLegacyTokenKeys)(r.legacyKeys??null),_index.Logger.info("[@webority/mobile-core] user auth wired to the store")};exports.initUserAuth=initUserAuth;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.initUserAuth=void 0;var _clientHeaders=require("./api/clientHeaders.js"),_userClient=require("./api/userClient.js"),_authStore=require("./auth/authStore.js"),_index=require("./logger/index.js");const initUserAuth=(e,r)=>{if(!e)throw new Error("Redux store is required for user package initialization");if(!r.logout||!r.refresh?.path)throw new Error("initUserAuth needs a logout action and refresh.path");(0,_userClient.injectStore)(e),(0,_userClient.injectUserAuth)(r),(0,_clientHeaders.setInstallationIdProvider)(r.installationId??null),(0,_authStore.setLegacyTokenKeys)(r.legacyKeys??null),_index.Logger.info("[@webority/mobile-core] user auth wired to the store")};exports.initUserAuth=initUserAuth;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.OutboxSignedOutError=exports.OutboxMissingKeyError=exports.OutboxFullError=void 0;class OutboxFullError extends Error{constructor(){super("There are too many reports waiting to send. Discard one or wait until you are back online."),this.name="OutboxFullError",Object.setPrototypeOf(this,OutboxFullError.prototype)}}exports.OutboxFullError=OutboxFullError;class OutboxSignedOutError extends Error{constructor(){super("Sign in to send this."),this.name="OutboxSignedOutError",Object.setPrototypeOf(this,OutboxSignedOutError.prototype)}}exports.OutboxSignedOutError=OutboxSignedOutError;class OutboxMissingKeyError extends Error{constructor(){super("An outbox request needs an Idempotency-Key header."),this.name="OutboxMissingKeyError",Object.setPrototypeOf(this,OutboxMissingKeyError.prototype)}}exports.OutboxMissingKeyError=OutboxMissingKeyError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.persistRequestFiles=exports.deleteEntryFiles=void 0;var _expoFileSystem=require("expo-file-system");const ROOT="webority-outbox",SAVE_FAILED="A file to send could not be saved. Attach it again.",safeFileName=e=>{const t=e.split(/[/\\]/).pop()??"",i=Array.from(t).filter(e=>(e.codePointAt(0)??0)>31).join("").trim();return""===i||"."===i||".."===i?"attachment":i},entryFolder=e=>new _expoFileSystem.Directory(_expoFileSystem.Paths.document,ROOT,e),saveFailed=e=>(e.exists&&e.delete(),new Error(SAVE_FAILED)),persistRequestFiles=async(e,t)=>{if("multipart"!==t.body.kind)return t;const i=entryFolder(e);i.create({intermediates:!0,idempotent:!0});const s=[];for(const[e,r]of t.body.fields.entries()){if(!("file"in r)){s.push(r);continue}const t=new _expoFileSystem.File(i,`${e}-${safeFileName(r.file.name)}`);try{await new _expoFileSystem.File(r.file.uri).copy(t,{overwrite:!0})}catch{throw saveFailed(i)}if(!t.exists||0===t.size)throw saveFailed(i);s.push({name:r.name,file:{...r.file,uri:t.uri}})}return{...t,body:{kind:"multipart",fields:s}}};exports.persistRequestFiles=persistRequestFiles;const deleteEntryFiles=async e=>{const t=entryFolder(e);t.exists&&t.delete()};exports.deleteEntryFiles=deleteEntryFiles;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"OutboxFullError",{enumerable:!0,get:function(){return _errors.OutboxFullError}}),Object.defineProperty(exports,"OutboxMissingKeyError",{enumerable:!0,get:function(){return _errors.OutboxMissingKeyError}}),Object.defineProperty(exports,"OutboxSignedOutError",{enumerable:!0,get:function(){return _errors.OutboxSignedOutError}}),Object.defineProperty(exports,"createOutbox",{enumerable:!0,get:function(){return _outbox.createOutbox}});var _errors=require("./errors.js"),_outbox=require("./outbox.js");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.createOutbox=void 0;var _axios=_interopRequireDefault(require("axios")),_reactNative=require("react-native"),_clientHeaders=require("../api/clientHeaders.js"),_idempotencyKey=require("../api/idempotencyKey.js"),_retry=require("../api/retry.js"),_tokenRefresh=require("../api/tokenRefresh.js"),_authStore=require("../auth/authStore.js"),_jwt=require("../auth/jwt.js"),_extractApiError=require("../errors/extractApiError.js"),_index=require("../logger/index.js"),_networkStatus=require("../network/networkStatus.js"),_index2=require("../sqlite/index.js"),_errors=require("./errors.js"),_files=require("./files.js");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const TABLE="outbox_entry",DEFAULT_DATABASE_NAME="webority-outbox",DEFAULT_MAX_ENTRIES=50,DEFAULT_KEEP_DAYS=14,DEFAULT_TIMEOUT_MS=3e5,BASE_BACKOFF_MS=3e4,MAX_BACKOFF_MS=9e5,DAY_MS=864e5,UUID_SHAPE=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,MIGRATIONS=[{version:1,name:"outbox_entry",up:[`CREATE TABLE ${TABLE} (\n id TEXT PRIMARY KEY,\n owner TEXT NOT NULL,\n queue TEXT NOT NULL,\n label TEXT NOT NULL,\n request_json TEXT NOT NULL,\n state TEXT NOT NULL,\n attempts INTEGER NOT NULL,\n last_failure_json TEXT NULL,\n created_utc TEXT NOT NULL,\n next_attempt_utc TEXT NOT NULL\n )`,`CREATE INDEX outbox_entry_owner_queue_created ON ${TABLE} (owner, queue, created_utc)`]}],nowIso=()=>(new Date).toISOString(),inMs=e=>new Date(Date.now()+e).toISOString(),toEntry=e=>({id:e.id,queue:e.queue,label:e.label,request:JSON.parse(e.request_json),state:e.state,attempts:e.attempts,lastFailure:null===e.last_failure_json?null:JSON.parse(e.last_failure_json),createdDateTimeUtc:e.created_utc,nextAttemptDateTimeUtc:e.next_attempt_utc}),currentIdentity=async()=>{const e=(await(0,_authStore.getToken)(_authStore.ACCESS_TOKEN_KEY))?.token,t=e?(0,_jwt.decodeJWT)(e)?.sub:void 0;if(!t)return null;const r=await(0,_clientHeaders.readAccountId)((0,_tokenRefresh.getAccountIdProvider)());return{owner:`${t}|${r??""}`,accountId:r}},assertRequestHeaders=e=>{const t=Object.keys(e),r=_clientHeaders.ACCOUNT_ID_HEADER.toLowerCase();for(const e of t){const t=e.toLowerCase();if("authorization"===t||t===r)throw new TypeError(`Outbox requests must not set the ${e} header.`)}const a=_retry.IDEMPOTENCY_KEY_HEADER.toLowerCase(),n=t.find(e=>e.toLowerCase()===a),s=void 0===n?void 0:e[n];if(void 0===s||!UUID_SHAPE.test(s))throw new _errors.OutboxMissingKeyError},isTransient=e=>{if(e instanceof Error&&"RequestOfflineError"===e.name)return!0;if(!_axios.default.isAxiosError(e))return!1;if(!e.response||(0,_retry.isNeverSentError)(e))return!0;const t=e.response.status;return 408===t||429===t||t>=500},retryDelayMs=(e,t)=>(0,_retry.retryAfterMs)(e)??Math.min(9e5,3e4*2**(t-1)),failureOf=e=>{const t=(0,_extractApiError.extractApiError)(e);return{code:t.code??"unknown",message:t.message,status:0===t.status?null:t.status}},buildFormData=e=>{const t=new FormData;for(const r of e)"file"in r?t.append(r.name,r.file):t.append(r.name,r.value);return t},createOutbox=e=>{const{http:t}=e,r=e.databaseName??"webority-outbox",a=e.maxEntriesPerOwner??50,n=e.keepDays??14,s=new Set,i=new Map;let o=null,u=null,c=!1,d=null,l=0,w=null;const store=()=>(o||(o=(0,_index2.openDatabase)(r).then(async e=>(await e.migrate(MIGRATIONS),e)).catch(e=>{throw o=null,e})),o),logFailure=e=>_index.Logger.error("[outbox] background work failed",e),emit=e=>{for(const t of s)t(e)},clearTimer=()=>{null!==d&&(clearTimeout(d),d=null)},flushNow=()=>(w||(w=runFlush().finally(()=>{w=null})),w),scheduleNext=async()=>{const e=++l;if(clearTimer(),!c||!u)return;const t=await store(),r=await currentIdentity();if(!r)return;const a=await t.selectOne(`SELECT MIN(next_attempt_utc) AS next FROM ${TABLE} WHERE owner = ? AND state != 'Failed'`,[r.owner]);if(e!==l||!a?.next)return;const n=Math.min(Math.max(0,Date.parse(a.next)-Date.now()),9e5);d=setTimeout(()=>{d=null,flushNow().catch(logFailure)},n)},notifyChanged=e=>{emit({type:"changed",queue:e}),scheduleNext().catch(logFailure)},runFlush=async()=>{const e=await store(),t=await currentIdentity();if(!t)return;await(async e=>{const t=new Date(Date.now()-n*DAY_MS).toISOString(),r=await e.findAll(TABLE,{sql:"created_utc < ?",params:[t]});for(const{id:t}of r)await e.remove(TABLE,{id:t}),await(0,_files.deleteEntryFiles)(t)})(e);const r=await e.findAll(TABLE,{sql:"owner = ? AND state != 'Failed' AND next_attempt_utc <= ?",params:[t.owner,nowIso()]},{orderBy:"created_utc"});for(const e of r)await deliver(e.id,t,!1);await scheduleNext()},runDelivery=async(e,r,a)=>{const n=await store(),s=await n.findOne(TABLE,{id:e,owner:r.owner});if(!s)return null;const i={...toEntry(s),state:"Sending"};await n.update(TABLE,{state:"Sending"},{id:e}),notifyChanged(i.queue);const{request:o}=i,u={...o.headers};r.accountId&&(u[_clientHeaders.ACCOUNT_ID_HEADER]=r.accountId);const c="json"===o.body.kind?o.body.value:buildFormData(o.body.fields);let d;try{d=await t.request({method:o.method,url:o.url,headers:u,data:c,timeout:o.timeoutMs??3e5,retry:!1})}catch(e){return(async(e,t,r,a)=>{if(isTransient(r)){const a=t.attempts+1,n=inMs(retryDelayMs(r,a));return await e.update(TABLE,{state:"Pending",attempts:a,next_attempt_utc:n},{id:t.id}),notifyChanged(t.queue),{status:"Queued",entry:{...t,state:"Pending",attempts:a,nextAttemptDateTimeUtc:n}}}const n=failureOf(r);if(a)return await e.remove(TABLE,{id:t.id}),await(0,_files.deleteEntryFiles)(t.id),notifyChanged(t.queue),{status:"Failed",entry:{...t,state:"Failed",lastFailure:n},failure:n};await e.update(TABLE,{state:"Failed",last_failure_json:JSON.stringify(n)},{id:t.id});const s={...t,state:"Failed",lastFailure:n};return notifyChanged(t.queue),emit({type:"failed",entry:s}),{status:"Failed",entry:s,failure:n}})(n,i,e,a)}return await n.remove(TABLE,{id:e}),await(0,_files.deleteEntryFiles)(e),notifyChanged(i.queue),emit({type:"sent",entry:i,httpStatus:d.status,data:d.data}),{status:"Sent",entry:i,httpStatus:d.status,data:d.data}},deliver=(e,t,r)=>{const a=i.get(e);if(a)return a;const n=runDelivery(e,t,r).finally(()=>{i.delete(e)});return i.set(e,n),n},start=async()=>{const e=await store();return u||((()=>{c="active"===_reactNative.AppState.currentState;const e=(0,_networkStatus.addNetworkStatusListener)(e=>{e.isConnected&&flushNow().catch(logFailure)}),t=_reactNative.AppState.addEventListener("change",e=>{c="active"===e,c?flushNow().catch(logFailure):clearTimer()});u=()=>{e(),t.remove()}})(),flushNow().catch(logFailure)),e};return{async send(e){assertRequestHeaders(e.request.headers);const t=await start(),r=await currentIdentity();if(!r)throw new _errors.OutboxSignedOutError;if(await t.count(TABLE,{owner:r.owner})>=a)throw new _errors.OutboxFullError;const n=(0,_idempotencyKey.newIdempotencyKey)(),s=await(0,_files.persistRequestFiles)(n,e.request),i=nowIso();try{await t.insert(TABLE,{id:n,owner:r.owner,queue:e.queue,label:e.label,request_json:JSON.stringify(s),state:"Pending",attempts:0,last_failure_json:null,created_utc:i,next_attempt_utc:i})}catch(e){throw await(0,_files.deleteEntryFiles)(n),e}notifyChanged(e.queue);const o=await deliver(n,r,!0);if(!o)throw new Error("The outbox entry was removed before it was sent.");return o},async list(e){const t=await start(),r=await currentIdentity();if(!r)return[];return(await t.findAll(TABLE,{owner:r.owner,queue:e},{orderBy:"created_utc"})).map(toEntry)},async retry(e){const t=await start(),r=await currentIdentity();if(!r)throw new _errors.OutboxSignedOutError;const a=0===await t.update(TABLE,{state:"Pending",last_failure_json:null,next_attempt_utc:nowIso()},{id:e,owner:r.owner})?null:await deliver(e,r,!1);if(!a)throw new Error("The outbox entry was not found.");return a},async discard(e){const t=await start(),r=await currentIdentity();if(!r)return;await(i.get(e)?.catch(()=>{}));const a=await t.findOne(TABLE,{id:e,owner:r.owner});a&&(await t.remove(TABLE,{id:e,owner:r.owner}),await(0,_files.deleteEntryFiles)(e),notifyChanged(a.queue))},flush:async()=>(await start(),flushNow()),subscribe:e=>(s.add(e),()=>{s.delete(e)}),async close(){l+=1,clearTimer(),u?.(),u=null,c=!1}}};exports.createOutbox=createOutbox;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.createApiBaseQuery=void 0;var _axios=_interopRequireDefault(require("axios")),_index=require("../errors/index.js");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const createApiBaseQuery=({client:e,publicClient:t})=>async(r,{signal:
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.createApiBaseQuery=void 0;var _axios=_interopRequireDefault(require("axios")),_index=require("../errors/index.js"),_index2=require("../logger/index.js");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const encodeParam=e=>e instanceof Date?encodeURIComponent(e.toISOString()):encodeURIComponent("object"==typeof e?JSON.stringify(e):String(e)),serializeParams=e=>t=>{const r=[];for(const[a,s]of Object.entries(t)){if(null==s)continue;const t=encodeURIComponent(a);if(Array.isArray(s))if("comma"===e)r.push(`${t}=${s.map(encodeParam).join(",")}`);else{const a="brackets"===e?`${t}[]`:t;for(const e of s)r.push(`${a}=${encodeParam(e)}`)}else r.push(`${t}=${encodeParam(s)}`)}return r.join("&")},createApiBaseQuery=({client:e,publicClient:t})=>async(r,{signal:a},s)=>{const i="string"==typeof r?{url:r}:r,o=i.silent??s?.silent??!1,n=i.expectedStatuses??s?.expectedStatuses,u=i.paramsFormat??s?.paramsFormat;if(i.public&&!t)throw new Error(`createApiBaseQuery: "${i.url}" is marked public but no publicClient was passed.`);const c=i.public?t:e,p={url:i.url,method:i.method??"GET",data:i.data,params:i.params,paramsSerializer:u?serializeParams(u):void 0,headers:i.headers,responseType:i.responseType,timeout:i.timeout,signal:a,skipErrorLog:!0};try{const e=await c.request(p);return{data:e.data,meta:{silent:o,status:e.status}}}catch(e){const t=(0,_index.extractApiError)(e),r=_axios.default.isCancel(e);return r||_index2.Logger.requestFailed(e,{expectedStatuses:n}),{error:t,meta:{silent:o||r,status:t.status,...n&&{expectedStatuses:n}}}}};exports.createApiBaseQuery=createApiBaseQuery;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.errorToastMiddleware=errorToastMiddleware,exports.isSilentRejection=void 0;var _workspace=require("../api/workspace.js"),_extractApiError=require("../errors/extractApiError.js");const isDict=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),hasSilent=e=>isDict(e)&&!0===e.silent,isSilentRejection=e=>hasSilent(e)||hasSilent(e.arg)||isDict(e.arg)&&hasSilent(e.arg.originalArgs)||hasSilent(e.baseQueryMeta);function errorToastMiddleware(e){const{showToast:
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.errorToastMiddleware=errorToastMiddleware,exports.isSilentRejection=void 0;var _workspace=require("../api/workspace.js"),_extractApiError=require("../errors/extractApiError.js");const isDict=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),hasSilent=e=>isDict(e)&&!0===e.silent,isSilentRejection=e=>hasSilent(e)||hasSilent(e.arg)||isDict(e.arg)&&hasSilent(e.arg.originalArgs)||hasSilent(e.baseQueryMeta);exports.isSilentRejection=isSilentRejection;const isExpectedRejection=(e,t)=>{const r=isDict(e.baseQueryMeta)?e.baseQueryMeta.expectedStatuses:void 0;return Array.isArray(r)&&r.includes(t)};function errorToastMiddleware(e){const{showToast:t,ignoreCodes:r=[],ignoreStatuses:s=[401],dedupeMs:i=4e3,onRejected:o}=e,n=new Map;return e=>a=>c=>{const u=a(c);if(!isDict(c)||!isDict(c.meta))return u;const d=c.meta;if("rejected"!==d.requestStatus||!0===d.aborted||!0===d.condition)return u;const l=(0,_extractApiError.extractApiError)(!0===d.rejectedWithValue?c.payload:c.error);if(l.code===_extractApiError.REQUEST_CANCELED_CODE)return u;const p=o?.(c,l,e);if("silent"===p||isSilentRejection(d)||isExpectedRejection(d,l.status))return u;if("toast"!==p){if(null!==l.code&&(l.code===_workspace.WORKSPACE_CHANGED_CODE||r.includes(l.code)))return u;if(s.includes(l.status))return u;if(Object.keys(l.fieldErrors).length>0)return u}return(e=>{if(i<=0)return!0;const t=Date.now();for(const[e,r]of n)t-r>=i&&n.delete(e);return!n.has(e)&&(n.set(e,t),!0)})(l.message)&&t(l.message,l),u}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{getConfigValue}from"../config/index.js";import{readAppBuild}from"../versionCheck/appBuild.js";export const CLIENT_BUILD_HEADER="Client-Build";export const APP_BUILD_HEADER="App-Build";export const CLIENT_KIND_HEADER="Client-Kind";export const CLIENT_APP_HEADER="Client-App";export const ACCOUNT_ID_HEADER="Account-Id";export const CLIENT_KIND="MobileApp";export const getClientBuild=()=>{const t=getConfigValue("appVersion");if(!t)return null;const
|
|
1
|
+
"use strict";import{getConfigValue}from"../config/index.js";import{readAppBuild}from"../versionCheck/appBuild.js";export const CLIENT_BUILD_HEADER="Client-Build";export const APP_BUILD_HEADER="App-Build";export const CLIENT_KIND_HEADER="Client-Kind";export const CLIENT_APP_HEADER="Client-App";export const ACCOUNT_ID_HEADER="Account-Id";export const INSTALLATION_ID_HEADER="Installation-Id";export const CLIENT_KIND="MobileApp";export const getClientBuild=()=>{const t=getConfigValue("appVersion");if(!t)return null;const n=getConfigValue("commit");return n?`${t}+${n}`:t};const setIfAbsent=(t,n,e)=>{e&&!t.has(n)&&t.set(n,e)};let installationIdProvider=null,installationId=null;export const setInstallationIdProvider=t=>{installationIdProvider=t,installationId=null};const resolveInstallationId=()=>{if(!installationIdProvider)return null;if(!installationId){const t=installationIdProvider();installationId=t,t.catch(()=>{installationId===t&&(installationId=null)})}return installationId};export const applyClientHeaders=t=>{t.interceptors.request.use(async t=>{t.headers.has("Installation-Id")||setIfAbsent(t.headers,"Installation-Id",await resolveInstallationId()),setIfAbsent(t.headers,"Client-Kind","MobileApp"),setIfAbsent(t.headers,"Client-App",getConfigValue("appId")),setIfAbsent(t.headers,"Client-Build",getClientBuild());const n=readAppBuild();return setIfAbsent(t.headers,"App-Build",null===n?null:String(n)),t})};export const readAccountId=async t=>t&&await t()||null;export const stampAccountId=async(t,n)=>{if(void 0!==t._accountId)return void(t._accountId&&t.headers.set("Account-Id",t._accountId));const e=t.headers.get("Account-Id");if("string"==typeof e&&""!==e)return void(t._accountId=e);const o=await readAccountId(n);t._accountId=o,o&&t.headers.set("Account-Id",o)};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const cryptoApi=()=>globalThis.crypto,randomBytes16=()=>{const t=new Uint8Array(16),o=cryptoApi();if("function"==typeof o?.getRandomValues)o.getRandomValues(t);else for(let o=0;o<t.length;o+=1)t[o]=Math.floor(256*Math.random());return t},formatUuid=t=>{const o=Array.from(t,t=>t.toString(16).padStart(2,"0")).join("");return`${o.slice(0,8)}-${o.slice(8,12)}-${o.slice(12,16)}-${o.slice(16,20)}-${o.slice(20,32)}`};export const newIdempotencyKey=()=>{const t=cryptoApi();if("function"==typeof t?.randomUUID)return t.randomUUID();const o=randomBytes16();return o[6]=15&o[6]|64,o[8]=63&o[8]|128,formatUuid(o)};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export const copyText=e=>require("expo-clipboard").setStringAsync(e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const SERVER_FAILURE_MESSAGE="Something went wrong on our side. Please try again in a moment.";export const OFFLINE_MESSAGE="You appear to be offline. Check your connection and try again.";export const TIMEOUT_MESSAGE="That took too long to respond. Check your connection and try again.";export const UNEXPECTED_MESSAGE="Something went wrong. Please try again.";export const UNREACHABLE_MESSAGE="We couldn't reach the server. Check your connection and try again.";export const REQUEST_CANCELED_CODE="request_canceled";export const CONTRACT_ERROR_CODE="contract_error";export const TIMEOUT_CODE="timeout";export const NETWORK_CODE="network";export const OFFLINE_CODE="offline";const INTERNAL_ERROR_CODE="internal_error",MAX_MESSAGE_LENGTH=300,requestFailedMessage=e=>`Request failed (${e})`,isDict=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),nonEmptyString=e=>"string"==typeof e&&e.trim().length>0?e:null,looksLikeDiagnostics=e=>e.length>300||/^\s*</.test(e)||e.includes("\n at ")||/(Exception|StackTrace):/.test(e)||/\b(System|Microsoft)\.[A-Za-z]+\.[A-Za-z]/.test(e),userSafe=e=>{const t=nonEmptyString(e);return null===t||looksLikeDiagnostics(t)?null:t};export const toFieldPath=e=>e.replace(/^\$\.?/,"").split(".").map(e=>e.charAt(0).toLowerCase()+e.slice(1)).join(".");const firstMessage=e=>{if(Array.isArray(e)){for(const t of e){const e=nonEmptyString(t);if(null!==e)return e}return null}return nonEmptyString(e)},addError=(e,t,
|
|
1
|
+
"use strict";export const SERVER_FAILURE_MESSAGE="Something went wrong on our side. Please try again in a moment.";export const OFFLINE_MESSAGE="You appear to be offline. Check your connection and try again.";export const TIMEOUT_MESSAGE="That took too long to respond. Check your connection and try again.";export const UNEXPECTED_MESSAGE="Something went wrong. Please try again.";export const UNREACHABLE_MESSAGE="We couldn't reach the server. Check your connection and try again.";export const REQUEST_CANCELED_CODE="request_canceled";export const CONTRACT_ERROR_CODE="contract_error";export const TIMEOUT_CODE="timeout";export const NETWORK_CODE="network";export const OFFLINE_CODE="offline";const INTERNAL_ERROR_CODE="internal_error",MAX_MESSAGE_LENGTH=300,requestFailedMessage=e=>`Request failed (${e})`,FLEET_DEFAULT_REFUSALS={401:{code:"unauthorized",sentence:"Please sign in to continue."},403:{code:"forbidden",sentence:"You do not have access to this."}},isDict=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),nonEmptyString=e=>"string"==typeof e&&e.trim().length>0?e:null,fleetDefaultRefusalSentence=(e,t)=>{const n=FLEET_DEFAULT_REFUSALS[e];if(void 0===n||null===t||t.code!==n.code)return null;const r=nonEmptyString(t.detail);return null===r||r===n.sentence?n.sentence:null},looksLikeDiagnostics=e=>e.length>300||/^\s*</.test(e)||e.includes("\n at ")||/(Exception|StackTrace):/.test(e)||/\b(System|Microsoft)\.[A-Za-z]+\.[A-Za-z]/.test(e),userSafe=e=>{const t=nonEmptyString(e);return null===t||looksLikeDiagnostics(t)?null:t};export const toFieldPath=e=>e.replace(/^\$\.?/,"").split(".").map(e=>e.charAt(0).toLowerCase()+e.slice(1)).join(".");const firstMessage=e=>{if(Array.isArray(e)){for(const t of e){const e=nonEmptyString(t);if(null!==e)return e}return null}return nonEmptyString(e)},addError=(e,t,n)=>{const r=toFieldPath(t);""===r?e.form??=n:r in e.fields||(e.fields[r]=n)},readErrors=e=>{const t={fields:{},form:null};if(Array.isArray(e)){for(const n of e){if(!isDict(n))continue;const e=nonEmptyString(n.message);null!==e&&addError(t,"string"==typeof n.field?n.field:"",e)}return t}if(!isDict(e))return t;for(const[n,r]of Object.entries(e)){const e=firstMessage(r);null!==e&&addError(t,n,e)}return t};export const isApiError=e=>isDict(e)&&"string"==typeof e.message&&"number"==typeof e.status&&"boolean"==typeof e.offline&&isDict(e.fieldErrors);const build=e=>({code:null,fieldErrors:{},status:0,offline:!1,traceId:null,diagnostic:null,...e}),requestTraceId=e=>{const t=isDict(e.config)?e.config.headers:void 0;if(!isDict(t))return null;const n="function"==typeof t.get?t.get("traceparent"):t.traceparent??t.Traceparent,r="string"==typeof n?/^00-([0-9a-f]{32})-[0-9a-f]{16}-[0-9a-f]{2}$/.exec(n):null;return r?r[1]:null},fromNoResponse=e=>{const t=nonEmptyString(e.code),n=nonEmptyString(e.name),r=nonEmptyString(e.message),o=requestTraceId(e);return build("CanceledError"===n||"ERR_CANCELED"===t?{code:"request_canceled",message:UNEXPECTED_MESSAGE,traceId:o,diagnostic:r}:"ECONNABORTED"===t||"ETIMEDOUT"===t?{code:"timeout",message:TIMEOUT_MESSAGE,offline:!0,traceId:o,diagnostic:r}:"RequestOfflineError"===n?{code:"offline",message:OFFLINE_MESSAGE,offline:!0,traceId:o,diagnostic:r}:"ERR_NETWORK"===t||"Network Error"===r||"Network request failed"===r?{code:"network",message:UNREACHABLE_MESSAGE,offline:!0,traceId:o,diagnostic:r}:{message:UNEXPECTED_MESSAGE,traceId:o,diagnostic:r})};export function extractApiError(e){if(isApiError(e))return e;if("string"==typeof e)return build({message:userSafe(e)??UNEXPECTED_MESSAGE,diagnostic:e||null});if(!isDict(e))return build({message:UNEXPECTED_MESSAGE,diagnostic:null==e?null:String(e)});if(!0===e.isContractError)return build({code:"contract_error",message:userSafe(e.message)??UNEXPECTED_MESSAGE,diagnostic:nonEmptyString(e.message)});const t=isDict(e.response)?e.response:null,n="number"==typeof t?.status?t.status:"number"==typeof e.status?e.status:0,r=t?t.data:e.body;if(0===n&&null==r)return fromNoResponse(e);const o=isDict(r)?r:null,{fields:s,form:i}=readErrors(o?.errors),a=nonEmptyString(o?.code),E=nonEmptyString(o?.traceId)??requestTraceId(e),c=nonEmptyString(o?.detail)??nonEmptyString(o?.title)??nonEmptyString(r)??nonEmptyString(e.message);let l;if(n>=500){l=(null!==a&&"internal_error"!==a?userSafe(o?.detail):null)??SERVER_FAILURE_MESSAGE}else l=fleetDefaultRefusalSentence(n,o)??userSafe(Object.values(s)[0])??userSafe(i)??userSafe(o?.detail)??userSafe(o?.title)??userSafe(r)??(n?requestFailedMessage(n):UNEXPECTED_MESSAGE);return build({code:a,message:l,fieldErrors:s,status:n,traceId:E,diagnostic:c})}export const isNoResponse=e=>extractApiError(e).offline;export function apiErrorMessage(e,t){const n=extractApiError(e);if(n.offline||null!==t&&!t)return n.message;return n.message===SERVER_FAILURE_MESSAGE||"request_canceled"===n.code||n.message===UNEXPECTED_MESSAGE||n.message===requestFailedMessage(n.status)?t??null:n.message}
|
package/lib/module/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export{ACCOUNT_ID_HEADER,CLIENT_BUILD_HEADER,CLIENT_KIND,CLIENT_KIND_HEADER,getClientBuild}from"./api/clientHeaders.js";export{buildCurl,logCurl}from"./api/curl.js";export{addMinAppVersionListener,getMinAppVersion,MIN_APP_VERSION_HEADER}from"./api/minAppVersion.js";export{default as publicClient}from"./api/publicClient.js";export{applyRequestDefaults,newTraceparent,TRACEPARENT_HEADER}from"./api/requestDefaults.js";export{attachRetry,IDEMPOTENCY_KEY_HEADER,isNeverSentError,isRetryableFailure,isRetryableStatus,resendWhenUnanswered,retryAfterMs}from"./api/retry.js";export{refreshAccessToken}from"./api/tokenRefresh.js";export{default as userClient,injectStore,injectUserAuth,RequestOfflineError,resetRefreshState,SESSION_EXPIRED_CODE,SESSION_REVOKED_CODE}from"./api/userClient.js";export{isWorkspaceChangedError,WORKSPACE_CHANGED_CODE,WorkspaceChangedError}from"./api/workspace.js";export{ACCESS_TOKEN_KEY,addSessionEndedListener,clearSession,getSessionUser,getToken,LEGACY_REFRESH_TOKEN_LIFETIME_MS,REFRESH_TOKEN_KEY,removeSessionUser,removeToken,SESSION_USER_KEY,setKeychainImplementation,setLegacyTokenKeys,storeSessionUser,storeToken}from"./auth/authStore.js";export{decodeJWT,getJWTExpiry,isJWTExpired}from"./auth/jwt.js";export{getConfig,getConfigValue,resetConfig,setConfig}from"./config/index.js";export{ENVIRONMENT_APP_ID_SUFFIX,installedAppId}from"./config/appIdentity.js";export{DeepLink,parseDeepLink,useDeepLink}from"./deepLink/index.js";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"./errors/index.js";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,groupingForLocale,isDateAfter,isDateBefore,isSameDay,isSupportedCountry,isValidNationalNumber,isValidPhoneNumber,maxNationalNumberLength,normalizePhone,parsePhoneNumber,parsePhoneNumberFromString,splitPhoneNumber,startOfDay,validatePhoneNumberLength}from"./formatters/index.js";export{initWebority}from"./initSDK.js";export{initUserAuth}from"./initUserAuth.js";export{configureLogger,getDeviceContext,Logger,setDeviceContext}from"./logger/index.js";export{crashlyticsRemoteLogger}from"./logger/crashlytics.js";export{addNetworkStatusListener,getNetworkStatus,setNetworkStatusImplementation,useNetworkStatus}from"./network/index.js";export{PUSH_STATUS}from"./push/status.js";export{isStorageAvailable,Storage,setStorageImplementation}from"./storage/index.js";export{encodeBase64}from"./utils/base64.js";export{isAadhaar,isAlphanumeric,isBetween,isEmail,isGstin,isHexColor,isIfsc,isIndianMobile,isIndianPincode,isInteger,isNonEmpty,isNumeric,isPan,isPhone,isStrongPassword,isUrl,maxLength,minLength}from"./validators/index.js";export{isBuildBelowMinimum,parseBuildNumber,setDeviceInfoImplementation,useVersionCheck,VersionCheck}from"./versionCheck/index.js";
|
|
1
|
+
"use strict";export{ACCOUNT_ID_HEADER,CLIENT_BUILD_HEADER,CLIENT_KIND,CLIENT_KIND_HEADER,getClientBuild}from"./api/clientHeaders.js";export{buildCurl,logCurl}from"./api/curl.js";export{newIdempotencyKey}from"./api/idempotencyKey.js";export{addMinAppVersionListener,getMinAppVersion,MIN_APP_VERSION_HEADER}from"./api/minAppVersion.js";export{default as publicClient}from"./api/publicClient.js";export{applyRequestDefaults,newTraceparent,TRACEPARENT_HEADER}from"./api/requestDefaults.js";export{attachRetry,IDEMPOTENCY_KEY_HEADER,isNeverSentError,isRetryableFailure,isRetryableStatus,resendWhenUnanswered,retryAfterMs}from"./api/retry.js";export{refreshAccessToken}from"./api/tokenRefresh.js";export{default as userClient,injectStore,injectUserAuth,RequestOfflineError,resetRefreshState,SESSION_EXPIRED_CODE,SESSION_REVOKED_CODE}from"./api/userClient.js";export{isWorkspaceChangedError,WORKSPACE_CHANGED_CODE,WorkspaceChangedError}from"./api/workspace.js";export{ACCESS_TOKEN_KEY,addSessionEndedListener,clearSession,getSessionUser,getToken,LEGACY_REFRESH_TOKEN_LIFETIME_MS,REFRESH_TOKEN_KEY,removeSessionUser,removeToken,SESSION_USER_KEY,setKeychainImplementation,setLegacyTokenKeys,storeSessionUser,storeToken}from"./auth/authStore.js";export{decodeJWT,getJWTExpiry,isJWTExpired}from"./auth/jwt.js";export{getConfig,getConfigValue,resetConfig,setConfig}from"./config/index.js";export{ENVIRONMENT_APP_ID_SUFFIX,installedAppId}from"./config/appIdentity.js";export{DeepLink,parseDeepLink,useDeepLink}from"./deepLink/index.js";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"./errors/index.js";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,groupingForLocale,isDateAfter,isDateBefore,isSameDay,isSupportedCountry,isValidNationalNumber,isValidPhoneNumber,maxNationalNumberLength,normalizePhone,parsePhoneNumber,parsePhoneNumberFromString,splitPhoneNumber,startOfDay,validatePhoneNumberLength}from"./formatters/index.js";export{initWebority}from"./initSDK.js";export{initUserAuth}from"./initUserAuth.js";export{configureLogger,getDeviceContext,Logger,setDeviceContext}from"./logger/index.js";export{crashlyticsRemoteLogger}from"./logger/crashlytics.js";export{addNetworkStatusListener,getNetworkStatus,setNetworkStatusImplementation,useNetworkStatus}from"./network/index.js";export{PUSH_STATUS}from"./push/status.js";export{isStorageAvailable,Storage,setStorageImplementation}from"./storage/index.js";export{encodeBase64}from"./utils/base64.js";export{isAadhaar,isAlphanumeric,isBetween,isEmail,isGstin,isHexColor,isIfsc,isIndianMobile,isIndianPincode,isInteger,isNonEmpty,isNumeric,isPan,isPhone,isStrongPassword,isUrl,maxLength,minLength}from"./validators/index.js";export{isBuildBelowMinimum,parseBuildNumber,setDeviceInfoImplementation,useVersionCheck,VersionCheck}from"./versionCheck/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{injectStore,injectUserAuth}from"./api/userClient.js";import{setLegacyTokenKeys}from"./auth/authStore.js";import{Logger}from"./logger/index.js";export const initUserAuth=(e,
|
|
1
|
+
"use strict";import{setInstallationIdProvider}from"./api/clientHeaders.js";import{injectStore,injectUserAuth}from"./api/userClient.js";import{setLegacyTokenKeys}from"./auth/authStore.js";import{Logger}from"./logger/index.js";export const initUserAuth=(e,t)=>{if(!e)throw new Error("Redux store is required for user package initialization");if(!t.logout||!t.refresh?.path)throw new Error("initUserAuth needs a logout action and refresh.path");injectStore(e),injectUserAuth(t),setInstallationIdProvider(t.installationId??null),setLegacyTokenKeys(t.legacyKeys??null),Logger.info("[@webority/mobile-core] user auth wired to the store")};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export class OutboxFullError extends Error{constructor(){super("There are too many reports waiting to send. Discard one or wait until you are back online."),this.name="OutboxFullError",Object.setPrototypeOf(this,OutboxFullError.prototype)}}export class OutboxSignedOutError extends Error{constructor(){super("Sign in to send this."),this.name="OutboxSignedOutError",Object.setPrototypeOf(this,OutboxSignedOutError.prototype)}}export class OutboxMissingKeyError extends Error{constructor(){super("An outbox request needs an Idempotency-Key header."),this.name="OutboxMissingKeyError",Object.setPrototypeOf(this,OutboxMissingKeyError.prototype)}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{Directory,File,Paths}from"expo-file-system";const ROOT="webority-outbox",SAVE_FAILED="A file to send could not be saved. Attach it again.",safeFileName=e=>{const t=e.split(/[/\\]/).pop()??"",i=Array.from(t).filter(e=>(e.codePointAt(0)??0)>31).join("").trim();return""===i||"."===i||".."===i?"attachment":i},entryFolder=e=>new Directory(Paths.document,ROOT,e),saveFailed=e=>(e.exists&&e.delete(),new Error(SAVE_FAILED));export const persistRequestFiles=async(e,t)=>{if("multipart"!==t.body.kind)return t;const i=entryFolder(e);i.create({intermediates:!0,idempotent:!0});const r=[];for(const[e,o]of t.body.fields.entries()){if(!("file"in o)){r.push(o);continue}const t=new File(i,`${e}-${safeFileName(o.file.name)}`);try{await new File(o.file.uri).copy(t,{overwrite:!0})}catch{throw saveFailed(i)}if(!t.exists||0===t.size)throw saveFailed(i);r.push({name:o.name,file:{...o.file,uri:t.uri}})}return{...t,body:{kind:"multipart",fields:r}}};export const deleteEntryFiles=async e=>{const t=entryFolder(e);t.exists&&t.delete()};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export{OutboxFullError,OutboxMissingKeyError,OutboxSignedOutError}from"./errors.js";export{createOutbox}from"./outbox.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import axios from"axios";import{AppState}from"react-native";import{ACCOUNT_ID_HEADER,readAccountId}from"../api/clientHeaders.js";import{newIdempotencyKey}from"../api/idempotencyKey.js";import{IDEMPOTENCY_KEY_HEADER,isNeverSentError,retryAfterMs}from"../api/retry.js";import{getAccountIdProvider}from"../api/tokenRefresh.js";import{ACCESS_TOKEN_KEY,getToken}from"../auth/authStore.js";import{decodeJWT}from"../auth/jwt.js";import{extractApiError}from"../errors/extractApiError.js";import{Logger}from"../logger/index.js";import{addNetworkStatusListener}from"../network/networkStatus.js";import{openDatabase}from"../sqlite/index.js";import{OutboxFullError,OutboxMissingKeyError,OutboxSignedOutError}from"./errors.js";import{deleteEntryFiles,persistRequestFiles}from"./files.js";const TABLE="outbox_entry",DEFAULT_DATABASE_NAME="webority-outbox",DEFAULT_MAX_ENTRIES=50,DEFAULT_KEEP_DAYS=14,DEFAULT_TIMEOUT_MS=3e5,BASE_BACKOFF_MS=3e4,MAX_BACKOFF_MS=9e5,DAY_MS=864e5,UUID_SHAPE=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,MIGRATIONS=[{version:1,name:"outbox_entry",up:[`CREATE TABLE ${TABLE} (\n id TEXT PRIMARY KEY,\n owner TEXT NOT NULL,\n queue TEXT NOT NULL,\n label TEXT NOT NULL,\n request_json TEXT NOT NULL,\n state TEXT NOT NULL,\n attempts INTEGER NOT NULL,\n last_failure_json TEXT NULL,\n created_utc TEXT NOT NULL,\n next_attempt_utc TEXT NOT NULL\n )`,`CREATE INDEX outbox_entry_owner_queue_created ON ${TABLE} (owner, queue, created_utc)`]}],nowIso=()=>(new Date).toISOString(),inMs=t=>new Date(Date.now()+t).toISOString(),toEntry=t=>({id:t.id,queue:t.queue,label:t.label,request:JSON.parse(t.request_json),state:t.state,attempts:t.attempts,lastFailure:null===t.last_failure_json?null:JSON.parse(t.last_failure_json),createdDateTimeUtc:t.created_utc,nextAttemptDateTimeUtc:t.next_attempt_utc}),currentIdentity=async()=>{const t=(await getToken(ACCESS_TOKEN_KEY))?.token,e=t?decodeJWT(t)?.sub:void 0;if(!e)return null;const r=await readAccountId(getAccountIdProvider());return{owner:`${e}|${r??""}`,accountId:r}},assertRequestHeaders=t=>{const e=Object.keys(t),r=ACCOUNT_ID_HEADER.toLowerCase();for(const t of e){const e=t.toLowerCase();if("authorization"===e||e===r)throw new TypeError(`Outbox requests must not set the ${t} header.`)}const a=IDEMPOTENCY_KEY_HEADER.toLowerCase(),n=e.find(t=>t.toLowerCase()===a),o=void 0===n?void 0:t[n];if(void 0===o||!UUID_SHAPE.test(o))throw new OutboxMissingKeyError},isTransient=t=>{if(t instanceof Error&&"RequestOfflineError"===t.name)return!0;if(!axios.isAxiosError(t))return!1;if(!t.response||isNeverSentError(t))return!0;const e=t.response.status;return 408===e||429===e||e>=500},retryDelayMs=(t,e)=>retryAfterMs(t)??Math.min(9e5,3e4*2**(e-1)),failureOf=t=>{const e=extractApiError(t);return{code:e.code??"unknown",message:e.message,status:0===e.status?null:e.status}},buildFormData=t=>{const e=new FormData;for(const r of t)"file"in r?e.append(r.name,r.file):e.append(r.name,r.value);return e};export const createOutbox=t=>{const{http:e}=t,r=t.databaseName??"webority-outbox",a=t.maxEntriesPerOwner??50,n=t.keepDays??14,o=new Set,s=new Map;let i=null,u=null,c=!1,d=null,l=0,w=null;const store=()=>(i||(i=openDatabase(r).then(async t=>(await t.migrate(MIGRATIONS),t)).catch(t=>{throw i=null,t})),i),logFailure=t=>Logger.error("[outbox] background work failed",t),emit=t=>{for(const e of o)e(t)},clearTimer=()=>{null!==d&&(clearTimeout(d),d=null)},flushNow=()=>(w||(w=runFlush().finally(()=>{w=null})),w),scheduleNext=async()=>{const t=++l;if(clearTimer(),!c||!u)return;const e=await store(),r=await currentIdentity();if(!r)return;const a=await e.selectOne(`SELECT MIN(next_attempt_utc) AS next FROM ${TABLE} WHERE owner = ? AND state != 'Failed'`,[r.owner]);if(t!==l||!a?.next)return;const n=Math.min(Math.max(0,Date.parse(a.next)-Date.now()),9e5);d=setTimeout(()=>{d=null,flushNow().catch(logFailure)},n)},notifyChanged=t=>{emit({type:"changed",queue:t}),scheduleNext().catch(logFailure)},runFlush=async()=>{const t=await store(),e=await currentIdentity();if(!e)return;await(async t=>{const e=new Date(Date.now()-n*DAY_MS).toISOString(),r=await t.findAll(TABLE,{sql:"created_utc < ?",params:[e]});for(const{id:e}of r)await t.remove(TABLE,{id:e}),await deleteEntryFiles(e)})(t);const r=await t.findAll(TABLE,{sql:"owner = ? AND state != 'Failed' AND next_attempt_utc <= ?",params:[e.owner,nowIso()]},{orderBy:"created_utc"});for(const t of r)await deliver(t.id,e,!1);await scheduleNext()},runDelivery=async(t,r,a)=>{const n=await store(),o=await n.findOne(TABLE,{id:t,owner:r.owner});if(!o)return null;const s={...toEntry(o),state:"Sending"};await n.update(TABLE,{state:"Sending"},{id:t}),notifyChanged(s.queue);const{request:i}=s,u={...i.headers};r.accountId&&(u[ACCOUNT_ID_HEADER]=r.accountId);const c="json"===i.body.kind?i.body.value:buildFormData(i.body.fields);let d;try{d=await e.request({method:i.method,url:i.url,headers:u,data:c,timeout:i.timeoutMs??3e5,retry:!1})}catch(t){return(async(t,e,r,a)=>{if(isTransient(r)){const a=e.attempts+1,n=inMs(retryDelayMs(r,a));return await t.update(TABLE,{state:"Pending",attempts:a,next_attempt_utc:n},{id:e.id}),notifyChanged(e.queue),{status:"Queued",entry:{...e,state:"Pending",attempts:a,nextAttemptDateTimeUtc:n}}}const n=failureOf(r);if(a)return await t.remove(TABLE,{id:e.id}),await deleteEntryFiles(e.id),notifyChanged(e.queue),{status:"Failed",entry:{...e,state:"Failed",lastFailure:n},failure:n};await t.update(TABLE,{state:"Failed",last_failure_json:JSON.stringify(n)},{id:e.id});const o={...e,state:"Failed",lastFailure:n};return notifyChanged(e.queue),emit({type:"failed",entry:o}),{status:"Failed",entry:o,failure:n}})(n,s,t,a)}return await n.remove(TABLE,{id:t}),await deleteEntryFiles(t),notifyChanged(s.queue),emit({type:"sent",entry:s,httpStatus:d.status,data:d.data}),{status:"Sent",entry:s,httpStatus:d.status,data:d.data}},deliver=(t,e,r)=>{const a=s.get(t);if(a)return a;const n=runDelivery(t,e,r).finally(()=>{s.delete(t)});return s.set(t,n),n},start=async()=>{const t=await store();return u||((()=>{c="active"===AppState.currentState;const t=addNetworkStatusListener(t=>{t.isConnected&&flushNow().catch(logFailure)}),e=AppState.addEventListener("change",t=>{c="active"===t,c?flushNow().catch(logFailure):clearTimer()});u=()=>{t(),e.remove()}})(),flushNow().catch(logFailure)),t};return{async send(t){assertRequestHeaders(t.request.headers);const e=await start(),r=await currentIdentity();if(!r)throw new OutboxSignedOutError;if(await e.count(TABLE,{owner:r.owner})>=a)throw new OutboxFullError;const n=newIdempotencyKey(),o=await persistRequestFiles(n,t.request),s=nowIso();try{await e.insert(TABLE,{id:n,owner:r.owner,queue:t.queue,label:t.label,request_json:JSON.stringify(o),state:"Pending",attempts:0,last_failure_json:null,created_utc:s,next_attempt_utc:s})}catch(t){throw await deleteEntryFiles(n),t}notifyChanged(t.queue);const i=await deliver(n,r,!0);if(!i)throw new Error("The outbox entry was removed before it was sent.");return i},async list(t){const e=await start(),r=await currentIdentity();if(!r)return[];return(await e.findAll(TABLE,{owner:r.owner,queue:t},{orderBy:"created_utc"})).map(toEntry)},async retry(t){const e=await start(),r=await currentIdentity();if(!r)throw new OutboxSignedOutError;const a=0===await e.update(TABLE,{state:"Pending",last_failure_json:null,next_attempt_utc:nowIso()},{id:t,owner:r.owner})?null:await deliver(t,r,!1);if(!a)throw new Error("The outbox entry was not found.");return a},async discard(t){const e=await start(),r=await currentIdentity();if(!r)return;await(s.get(t)?.catch(()=>{}));const a=await e.findOne(TABLE,{id:t,owner:r.owner});a&&(await e.remove(TABLE,{id:t,owner:r.owner}),await deleteEntryFiles(t),notifyChanged(a.queue))},flush:async()=>(await start(),flushNow()),subscribe:t=>(o.add(t),()=>{o.delete(t)}),async close(){l+=1,clearTimer(),u?.(),u=null,c=!1}}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import axios from"axios";import{extractApiError}from"../errors/index.js";export const createApiBaseQuery=({client:
|
|
1
|
+
"use strict";import axios from"axios";import{extractApiError}from"../errors/index.js";import{Logger}from"../logger/index.js";const encodeParam=e=>e instanceof Date?encodeURIComponent(e.toISOString()):encodeURIComponent("object"==typeof e?JSON.stringify(e):String(e)),serializeParams=e=>t=>{const r=[];for(const[s,a]of Object.entries(t)){if(null==a)continue;const t=encodeURIComponent(s);if(Array.isArray(a))if("comma"===e)r.push(`${t}=${a.map(encodeParam).join(",")}`);else{const s="brackets"===e?`${t}[]`:t;for(const e of a)r.push(`${s}=${encodeParam(e)}`)}else r.push(`${t}=${encodeParam(a)}`)}return r.join("&")};export const createApiBaseQuery=({client:e,publicClient:t})=>async(r,{signal:s},a)=>{const o="string"==typeof r?{url:r}:r,i=o.silent??a?.silent??!1,n=o.expectedStatuses??a?.expectedStatuses,c=o.paramsFormat??a?.paramsFormat;if(o.public&&!t)throw new Error(`createApiBaseQuery: "${o.url}" is marked public but no publicClient was passed.`);const p=o.public?t:e,u={url:o.url,method:o.method??"GET",data:o.data,params:o.params,paramsSerializer:c?serializeParams(c):void 0,headers:o.headers,responseType:o.responseType,timeout:o.timeout,signal:s,skipErrorLog:!0};try{const e=await p.request(u);return{data:e.data,meta:{silent:i,status:e.status}}}catch(e){const t=extractApiError(e),r=axios.isCancel(e);return r||Logger.requestFailed(e,{expectedStatuses:n}),{error:t,meta:{silent:i||r,status:t.status,...n&&{expectedStatuses:n}}}}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{WORKSPACE_CHANGED_CODE}from"../api/workspace.js";import{extractApiError,REQUEST_CANCELED_CODE}from"../errors/extractApiError.js";const isDict=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),hasSilent=e=>isDict(e)&&!0===e.silent;export const isSilentRejection=e=>hasSilent(e)||hasSilent(e.arg)||isDict(e.arg)&&hasSilent(e.arg.originalArgs)||hasSilent(e.baseQueryMeta);export function errorToastMiddleware(e){const{showToast:t,ignoreCodes:r=[],ignoreStatuses:s=[401],dedupeMs:i=4e3,onRejected:o}=e,n=new Map;return e=>a=>c=>{const u=a(c);if(!isDict(c)||!isDict(c.meta))return u;const
|
|
1
|
+
"use strict";import{WORKSPACE_CHANGED_CODE}from"../api/workspace.js";import{extractApiError,REQUEST_CANCELED_CODE}from"../errors/extractApiError.js";const isDict=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),hasSilent=e=>isDict(e)&&!0===e.silent;export const isSilentRejection=e=>hasSilent(e)||hasSilent(e.arg)||isDict(e.arg)&&hasSilent(e.arg.originalArgs)||hasSilent(e.baseQueryMeta);const isExpectedRejection=(e,t)=>{const r=isDict(e.baseQueryMeta)?e.baseQueryMeta.expectedStatuses:void 0;return Array.isArray(r)&&r.includes(t)};export function errorToastMiddleware(e){const{showToast:t,ignoreCodes:r=[],ignoreStatuses:s=[401],dedupeMs:i=4e3,onRejected:o}=e,n=new Map;return e=>a=>c=>{const u=a(c);if(!isDict(c)||!isDict(c.meta))return u;const d=c.meta;if("rejected"!==d.requestStatus||!0===d.aborted||!0===d.condition)return u;const l=extractApiError(!0===d.rejectedWithValue?c.payload:c.error);if(l.code===REQUEST_CANCELED_CODE)return u;const E=o?.(c,l,e);if("silent"===E||isSilentRejection(d)||isExpectedRejection(d,l.status))return u;if("toast"!==E){if(null!==l.code&&(l.code===WORKSPACE_CHANGED_CODE||r.includes(l.code)))return u;if(s.includes(l.status))return u;if(Object.keys(l.fieldErrors).length>0)return u}return(e=>{if(i<=0)return!0;const t=Date.now();for(const[e,r]of n)t-r>=i&&n.delete(e);return!n.has(e)&&(n.set(e,t),!0)})(l.message)&&t(l.message,l),u}}
|
|
@@ -4,11 +4,15 @@ export declare const APP_BUILD_HEADER = "App-Build";
|
|
|
4
4
|
export declare const CLIENT_KIND_HEADER = "Client-Kind";
|
|
5
5
|
export declare const CLIENT_APP_HEADER = "Client-App";
|
|
6
6
|
export declare const ACCOUNT_ID_HEADER = "Account-Id";
|
|
7
|
+
export declare const INSTALLATION_ID_HEADER = "Installation-Id";
|
|
7
8
|
/** The server picks session rules and the minimum version per kind; the names match its enum. */
|
|
8
9
|
export type ClientKind = "Browser" | "MobileApp";
|
|
9
10
|
export declare const CLIENT_KIND: ClientKind;
|
|
10
11
|
/** `<appVersion>+<commit>`, `<appVersion>` when no commit was stamped, `null` before init. */
|
|
11
12
|
export declare const getClientBuild: () => string | null;
|
|
13
|
+
export type InstallationIdProvider = () => Promise<string>;
|
|
14
|
+
/** Wires the app's installation id source, or none with `null`; the next request resolves it afresh. */
|
|
15
|
+
export declare const setInstallationIdProvider: (provider: InstallationIdProvider | null) => void;
|
|
12
16
|
/**
|
|
13
17
|
* Stamps Client-Kind, Client-Build and App-Build on every request, and Client-App with the
|
|
14
18
|
* config's app id when one is set, so the server can tell the apps of one kind apart.
|
|
@@ -16,7 +20,8 @@ export declare const getClientBuild: () => string | null;
|
|
|
16
20
|
* it is left off when the build is unknown, because the server never refuses a
|
|
17
21
|
* request without it and a guessed number could strand a current build. A value the app
|
|
18
22
|
* already set (a default header, or a per-request one) wins, so an app that
|
|
19
|
-
* wired them by hand keeps working unchanged.
|
|
23
|
+
* wired them by hand keeps working unchanged. Installation-Id is stamped only when
|
|
24
|
+
* `initUserAuth` was given an `installationId` provider.
|
|
20
25
|
*/
|
|
21
26
|
export declare const applyClientHeaders: (client: AxiosInstance) => void;
|
|
22
27
|
export type AccountIdProvider = () => string | null | undefined | Promise<string | null | undefined>;
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* where `errors` is a ModelState dictionary (`{ Field: ["msg"] }`) or a list of `{ field, message }`.
|
|
7
7
|
*
|
|
8
8
|
* Message precedence (react.md): first field error, form error, `detail`, `title`, a plain-text
|
|
9
|
-
* body, then `Request failed (<status>)`. A
|
|
10
|
-
*
|
|
9
|
+
* body, then `Request failed (<status>)`. A 401 or 403 whose body is the standard refusal (api.md)
|
|
10
|
+
* gets the library's sentence for it, ahead of those. A 5xx shows `detail` only when it carries a
|
|
11
|
+
* code other than `internal_error`. The server's text goes on `diagnostic` for the logger, never the screen.
|
|
11
12
|
* The trace id falls back to the request's own `traceparent`, so a lost request keeps a reference.
|
|
12
13
|
*/
|
|
13
14
|
export interface ApiError {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @webority/mobile-core/compressor expo-image-manipulator + expo-file-system
|
|
10
10
|
* @webority/mobile-core/geolocation a geolocation provider
|
|
11
11
|
* @webority/mobile-core/sqlite expo-sqlite
|
|
12
|
+
* @webority/mobile-core/outbox durable queued writes (expo-sqlite + expo-file-system)
|
|
12
13
|
* @webority/mobile-core/download a filesystem module
|
|
13
14
|
* @webority/mobile-core/installation installation id (expo-crypto)
|
|
14
15
|
* @webority/mobile-core/attachments fetch, preview cache and preview kind (expo-file-system)
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
export type { AccountIdProvider, ClientKind } from "./api/clientHeaders";
|
|
39
40
|
export { ACCOUNT_ID_HEADER, CLIENT_BUILD_HEADER, CLIENT_KIND, CLIENT_KIND_HEADER, getClientBuild, } from "./api/clientHeaders";
|
|
40
41
|
export { buildCurl, logCurl } from "./api/curl";
|
|
42
|
+
export { newIdempotencyKey } from "./api/idempotencyKey";
|
|
41
43
|
export type { MinAppVersionListener } from "./api/minAppVersion";
|
|
42
44
|
export { addMinAppVersionListener, getMinAppVersion, MIN_APP_VERSION_HEADER, } from "./api/minAppVersion";
|
|
43
45
|
export { default as publicClient } from "./api/publicClient";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AccountIdProvider, type InstallationIdProvider } from "./api/clientHeaders";
|
|
2
2
|
import { type LegacyTokenKeys } from "./auth/authStore";
|
|
3
3
|
/** The tokens a refresh response carries, with their expiry timestamps. */
|
|
4
4
|
export interface TokenRefreshResult {
|
|
@@ -43,6 +43,14 @@ export interface UserAuthOptions {
|
|
|
43
43
|
* Omit it in a product whose API takes the account from the token alone.
|
|
44
44
|
*/
|
|
45
45
|
accountId?: AccountIdProvider;
|
|
46
|
+
/**
|
|
47
|
+
* The device's installation id, sent as `Installation-Id` on every publicClient and
|
|
48
|
+
* userClient request. Resolved once, on the first request, and kept in memory. Pass the
|
|
49
|
+
* app's `getOrCreateInstallationId` (from `@webority/mobile-core/installation`); the
|
|
50
|
+
* clients never import it, so they load without the optional expo-crypto peer. Omit it
|
|
51
|
+
* and no header goes out.
|
|
52
|
+
*/
|
|
53
|
+
installationId?: InstallationIdProvider;
|
|
46
54
|
/**
|
|
47
55
|
* The secure-store keys the app kept its session under before this library. The first token
|
|
48
56
|
* read that finds the library's keys empty moves a session found there and deletes the old
|
|
@@ -59,7 +67,7 @@ export interface UserAuthOptions {
|
|
|
59
67
|
* so the tokens are gone and the session-ended listeners hear it, then dispatches `logout`.
|
|
60
68
|
*
|
|
61
69
|
* @example
|
|
62
|
-
* initUserAuth(store, { logout, refresh: { path: '/Account/RefreshToken' } });
|
|
70
|
+
* initUserAuth(store, { logout, refresh: { path: '/Account/RefreshToken' }, installationId: getOrCreateInstallationId });
|
|
63
71
|
*/
|
|
64
72
|
export declare const initUserAuth: <S>(store: S, options: UserAuthOptions) => void;
|
|
65
73
|
//# sourceMappingURL=initUserAuth.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class OutboxFullError extends Error {
|
|
2
|
+
constructor();
|
|
3
|
+
}
|
|
4
|
+
export declare class OutboxSignedOutError extends Error {
|
|
5
|
+
constructor();
|
|
6
|
+
}
|
|
7
|
+
export declare class OutboxMissingKeyError extends Error {
|
|
8
|
+
constructor();
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OutboxRequest } from "./types";
|
|
2
|
+
/** Copies each file part into Paths.document/webority-outbox/<entryId>/ and returns the request pointing at the copies; throws when a source is missing or empty (react-native.md 0-byte guard). */
|
|
3
|
+
export declare const persistRequestFiles: (entryId: string, request: OutboxRequest) => Promise<OutboxRequest>;
|
|
4
|
+
export declare const deleteEntryFiles: (entryId: string) => Promise<void>;
|
|
5
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
export type OutboxMethod = "POST" | "PUT" | "PATCH";
|
|
2
|
+
export interface OutboxFilePart {
|
|
3
|
+
uri: string;
|
|
4
|
+
name: string;
|
|
5
|
+
type: string;
|
|
6
|
+
}
|
|
7
|
+
export type OutboxFormField = {
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
} | {
|
|
11
|
+
name: string;
|
|
12
|
+
file: OutboxFilePart;
|
|
13
|
+
};
|
|
14
|
+
export type OutboxBody = {
|
|
15
|
+
kind: "json";
|
|
16
|
+
value: unknown;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "multipart";
|
|
19
|
+
fields: OutboxFormField[];
|
|
20
|
+
};
|
|
21
|
+
export interface OutboxRequest {
|
|
22
|
+
method: OutboxMethod;
|
|
23
|
+
/** As the http client takes it (relative to its base URL). */
|
|
24
|
+
url: string;
|
|
25
|
+
/** Must carry Idempotency-Key (a uuid); Authorization and Account-Id are refused, the outbox sets the workspace itself. */
|
|
26
|
+
headers: Record<string, string>;
|
|
27
|
+
body: OutboxBody;
|
|
28
|
+
timeoutMs?: number;
|
|
29
|
+
}
|
|
30
|
+
export type OutboxEntryState = "Pending" | "Sending" | "Failed";
|
|
31
|
+
export interface OutboxFailure {
|
|
32
|
+
code: string;
|
|
33
|
+
message: string;
|
|
34
|
+
status: number | null;
|
|
35
|
+
}
|
|
36
|
+
export interface OutboxEntry {
|
|
37
|
+
id: string;
|
|
38
|
+
queue: string;
|
|
39
|
+
/** Shown in lists: the ticket subject, the first words of a reply. */
|
|
40
|
+
label: string;
|
|
41
|
+
/** The request as it will be sent; file parts point at the outbox's own copies. */
|
|
42
|
+
request: OutboxRequest;
|
|
43
|
+
state: OutboxEntryState;
|
|
44
|
+
attempts: number;
|
|
45
|
+
lastFailure: OutboxFailure | null;
|
|
46
|
+
createdDateTimeUtc: string;
|
|
47
|
+
nextAttemptDateTimeUtc: string;
|
|
48
|
+
}
|
|
49
|
+
export type OutboxSendResult = {
|
|
50
|
+
status: "Sent";
|
|
51
|
+
entry: OutboxEntry;
|
|
52
|
+
httpStatus: number;
|
|
53
|
+
data: unknown;
|
|
54
|
+
} | {
|
|
55
|
+
status: "Queued";
|
|
56
|
+
entry: OutboxEntry;
|
|
57
|
+
} | {
|
|
58
|
+
status: "Failed";
|
|
59
|
+
entry: OutboxEntry;
|
|
60
|
+
failure: OutboxFailure;
|
|
61
|
+
};
|
|
62
|
+
export type OutboxEvent = {
|
|
63
|
+
type: "changed";
|
|
64
|
+
queue: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: "sent";
|
|
67
|
+
entry: OutboxEntry;
|
|
68
|
+
httpStatus: number;
|
|
69
|
+
data: unknown;
|
|
70
|
+
} | {
|
|
71
|
+
type: "failed";
|
|
72
|
+
entry: OutboxEntry;
|
|
73
|
+
};
|
|
74
|
+
export type OutboxListener = (event: OutboxEvent) => void;
|
|
75
|
+
/** The slice of the app's signed-in axios instance (mobile-core's userClient) the outbox sends through. */
|
|
76
|
+
export interface OutboxHttpClient {
|
|
77
|
+
request(config: {
|
|
78
|
+
method: string;
|
|
79
|
+
url: string;
|
|
80
|
+
headers: Record<string, string>;
|
|
81
|
+
data?: unknown;
|
|
82
|
+
timeout?: number;
|
|
83
|
+
retry?: false;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
status: number;
|
|
86
|
+
data: unknown;
|
|
87
|
+
}>;
|
|
88
|
+
}
|
|
89
|
+
export interface OutboxOptions {
|
|
90
|
+
http: OutboxHttpClient;
|
|
91
|
+
/** Default "webority-outbox". */
|
|
92
|
+
databaseName?: string;
|
|
93
|
+
/** Default 50; enqueue beyond it throws OutboxFullError. */
|
|
94
|
+
maxEntriesPerOwner?: number;
|
|
95
|
+
/** Default 14; older entries are deleted with their files. */
|
|
96
|
+
keepDays?: number;
|
|
97
|
+
}
|
|
98
|
+
export interface Outbox {
|
|
99
|
+
/** Stores the entry (files copied first), then tries it once. Definitive refusal on this first try deletes the entry and returns Failed. */
|
|
100
|
+
send(input: {
|
|
101
|
+
queue: string;
|
|
102
|
+
label: string;
|
|
103
|
+
request: OutboxRequest;
|
|
104
|
+
}): Promise<OutboxSendResult>;
|
|
105
|
+
/** The signed-in owner's entries of one queue, oldest first. */
|
|
106
|
+
list(queue: string): Promise<OutboxEntry[]>;
|
|
107
|
+
retry(id: string): Promise<OutboxSendResult>;
|
|
108
|
+
discard(id: string): Promise<void>;
|
|
109
|
+
/** Sends every due entry of the signed-in owner, one at a time, oldest first. */
|
|
110
|
+
flush(): Promise<void>;
|
|
111
|
+
subscribe(listener: OutboxListener): () => void;
|
|
112
|
+
/** Stops the listeners and timers (tests, hot reload). */
|
|
113
|
+
close(): Promise<void>;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -6,9 +6,14 @@ import { type ApiError } from "../errors";
|
|
|
6
6
|
*
|
|
7
7
|
* `silent` opts this call out of the error toast (decision 42); an endpoint can
|
|
8
8
|
* instead set it once for every call with `extraOptions: { silent: true }`.
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
9
|
+
* `expectedStatuses` lists the statuses the screen handles itself: a failure with
|
|
10
|
+
* one is logged at info, never recorded as an error. `public` sends the call
|
|
11
|
+
* through the anonymous client (sign-in, sign-up, a public lookup), so one
|
|
12
|
+
* `createApi` serves both clients. `paramsFormat` picks how a list in `params`
|
|
13
|
+
* reaches the query string; see `ParamsFormat`.
|
|
11
14
|
*/
|
|
15
|
+
/** `"repeat"` sends `a=1&a=2`, `"brackets"` sends `a[]=1&a[]=2`, `"comma"` sends `a=1,2`. */
|
|
16
|
+
export type ParamsFormat = "repeat" | "brackets" | "comma";
|
|
12
17
|
export interface ApiRequest {
|
|
13
18
|
url: string;
|
|
14
19
|
method?: Method;
|
|
@@ -21,12 +26,16 @@ export interface ApiRequest {
|
|
|
21
26
|
responseType?: Extract<ResponseType, "json" | "text">;
|
|
22
27
|
timeout?: number;
|
|
23
28
|
silent?: boolean;
|
|
29
|
+
expectedStatuses?: number[];
|
|
30
|
+
paramsFormat?: ParamsFormat;
|
|
24
31
|
public?: boolean;
|
|
25
32
|
}
|
|
26
33
|
export type ApiQueryArgs = string | ApiRequest;
|
|
27
34
|
/** Per-endpoint options, set as the endpoint's `extraOptions`. */
|
|
28
35
|
export interface ApiExtraOptions {
|
|
29
36
|
silent?: boolean;
|
|
37
|
+
expectedStatuses?: number[];
|
|
38
|
+
paramsFormat?: ParamsFormat;
|
|
30
39
|
}
|
|
31
40
|
/**
|
|
32
41
|
* Returned as the base query's `meta`, which RTK Query copies onto the
|
|
@@ -36,6 +45,8 @@ export interface ApiExtraOptions {
|
|
|
36
45
|
*/
|
|
37
46
|
export interface ApiBaseQueryMeta {
|
|
38
47
|
silent: boolean;
|
|
48
|
+
/** The statuses the call's screen handles itself; the toast middleware skips a failure with one. */
|
|
49
|
+
expectedStatuses?: number[];
|
|
39
50
|
/** The HTTP status, or 0 when no response arrived. */
|
|
40
51
|
status: number;
|
|
41
52
|
}
|
|
@@ -12,9 +12,13 @@ import { type ApiError } from "../errors/extractApiError";
|
|
|
12
12
|
* - an RTK Query endpoint: `extraOptions: { silent: true }`, which the base query copies
|
|
13
13
|
* onto its meta.
|
|
14
14
|
*
|
|
15
|
+
* An RTK Query call whose `expectedStatuses` holds the failure's status is never toasted, as
|
|
16
|
+
* with `silent`: the screen handles that status itself.
|
|
17
|
+
*
|
|
15
18
|
* Never toasted: an aborted thunk or a cancelled request (a screen unmounting), an RTK Query
|
|
16
19
|
* condition skip (the data is already cached), a 401 by default (the auth layer owns a dead
|
|
17
|
-
* session), a `workspace_changed` rejection (the request belonged to a workspace the user left)
|
|
20
|
+
* session), a `workspace_changed` rejection (the request belonged to a workspace the user left),
|
|
21
|
+
* a failure whose `fieldErrors` name a field (the form already shows each one inline).
|
|
18
22
|
* Identical messages are de-duplicated for `dedupeMs`, because a screen that fires
|
|
19
23
|
* four fetches and loses the network would otherwise stack four copies of one sentence.
|
|
20
24
|
*
|
|
@@ -4,11 +4,15 @@ export declare const APP_BUILD_HEADER = "App-Build";
|
|
|
4
4
|
export declare const CLIENT_KIND_HEADER = "Client-Kind";
|
|
5
5
|
export declare const CLIENT_APP_HEADER = "Client-App";
|
|
6
6
|
export declare const ACCOUNT_ID_HEADER = "Account-Id";
|
|
7
|
+
export declare const INSTALLATION_ID_HEADER = "Installation-Id";
|
|
7
8
|
/** The server picks session rules and the minimum version per kind; the names match its enum. */
|
|
8
9
|
export type ClientKind = "Browser" | "MobileApp";
|
|
9
10
|
export declare const CLIENT_KIND: ClientKind;
|
|
10
11
|
/** `<appVersion>+<commit>`, `<appVersion>` when no commit was stamped, `null` before init. */
|
|
11
12
|
export declare const getClientBuild: () => string | null;
|
|
13
|
+
export type InstallationIdProvider = () => Promise<string>;
|
|
14
|
+
/** Wires the app's installation id source, or none with `null`; the next request resolves it afresh. */
|
|
15
|
+
export declare const setInstallationIdProvider: (provider: InstallationIdProvider | null) => void;
|
|
12
16
|
/**
|
|
13
17
|
* Stamps Client-Kind, Client-Build and App-Build on every request, and Client-App with the
|
|
14
18
|
* config's app id when one is set, so the server can tell the apps of one kind apart.
|
|
@@ -16,7 +20,8 @@ export declare const getClientBuild: () => string | null;
|
|
|
16
20
|
* it is left off when the build is unknown, because the server never refuses a
|
|
17
21
|
* request without it and a guessed number could strand a current build. A value the app
|
|
18
22
|
* already set (a default header, or a per-request one) wins, so an app that
|
|
19
|
-
* wired them by hand keeps working unchanged.
|
|
23
|
+
* wired them by hand keeps working unchanged. Installation-Id is stamped only when
|
|
24
|
+
* `initUserAuth` was given an `installationId` provider.
|
|
20
25
|
*/
|
|
21
26
|
export declare const applyClientHeaders: (client: AxiosInstance) => void;
|
|
22
27
|
export type AccountIdProvider = () => string | null | undefined | Promise<string | null | undefined>;
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* where `errors` is a ModelState dictionary (`{ Field: ["msg"] }`) or a list of `{ field, message }`.
|
|
7
7
|
*
|
|
8
8
|
* Message precedence (react.md): first field error, form error, `detail`, `title`, a plain-text
|
|
9
|
-
* body, then `Request failed (<status>)`. A
|
|
10
|
-
*
|
|
9
|
+
* body, then `Request failed (<status>)`. A 401 or 403 whose body is the standard refusal (api.md)
|
|
10
|
+
* gets the library's sentence for it, ahead of those. A 5xx shows `detail` only when it carries a
|
|
11
|
+
* code other than `internal_error`. The server's text goes on `diagnostic` for the logger, never the screen.
|
|
11
12
|
* The trace id falls back to the request's own `traceparent`, so a lost request keeps a reference.
|
|
12
13
|
*/
|
|
13
14
|
export interface ApiError {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @webority/mobile-core/compressor expo-image-manipulator + expo-file-system
|
|
10
10
|
* @webority/mobile-core/geolocation a geolocation provider
|
|
11
11
|
* @webority/mobile-core/sqlite expo-sqlite
|
|
12
|
+
* @webority/mobile-core/outbox durable queued writes (expo-sqlite + expo-file-system)
|
|
12
13
|
* @webority/mobile-core/download a filesystem module
|
|
13
14
|
* @webority/mobile-core/installation installation id (expo-crypto)
|
|
14
15
|
* @webority/mobile-core/attachments fetch, preview cache and preview kind (expo-file-system)
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
export type { AccountIdProvider, ClientKind } from "./api/clientHeaders.js";
|
|
39
40
|
export { ACCOUNT_ID_HEADER, CLIENT_BUILD_HEADER, CLIENT_KIND, CLIENT_KIND_HEADER, getClientBuild, } from "./api/clientHeaders.js";
|
|
40
41
|
export { buildCurl, logCurl } from "./api/curl.js";
|
|
42
|
+
export { newIdempotencyKey } from "./api/idempotencyKey.js";
|
|
41
43
|
export type { MinAppVersionListener } from "./api/minAppVersion.js";
|
|
42
44
|
export { addMinAppVersionListener, getMinAppVersion, MIN_APP_VERSION_HEADER, } from "./api/minAppVersion.js";
|
|
43
45
|
export { default as publicClient } from "./api/publicClient.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AccountIdProvider, type InstallationIdProvider } from "./api/clientHeaders.js";
|
|
2
2
|
import { type LegacyTokenKeys } from "./auth/authStore.js";
|
|
3
3
|
/** The tokens a refresh response carries, with their expiry timestamps. */
|
|
4
4
|
export interface TokenRefreshResult {
|
|
@@ -43,6 +43,14 @@ export interface UserAuthOptions {
|
|
|
43
43
|
* Omit it in a product whose API takes the account from the token alone.
|
|
44
44
|
*/
|
|
45
45
|
accountId?: AccountIdProvider;
|
|
46
|
+
/**
|
|
47
|
+
* The device's installation id, sent as `Installation-Id` on every publicClient and
|
|
48
|
+
* userClient request. Resolved once, on the first request, and kept in memory. Pass the
|
|
49
|
+
* app's `getOrCreateInstallationId` (from `@webority/mobile-core/installation`); the
|
|
50
|
+
* clients never import it, so they load without the optional expo-crypto peer. Omit it
|
|
51
|
+
* and no header goes out.
|
|
52
|
+
*/
|
|
53
|
+
installationId?: InstallationIdProvider;
|
|
46
54
|
/**
|
|
47
55
|
* The secure-store keys the app kept its session under before this library. The first token
|
|
48
56
|
* read that finds the library's keys empty moves a session found there and deletes the old
|
|
@@ -59,7 +67,7 @@ export interface UserAuthOptions {
|
|
|
59
67
|
* so the tokens are gone and the session-ended listeners hear it, then dispatches `logout`.
|
|
60
68
|
*
|
|
61
69
|
* @example
|
|
62
|
-
* initUserAuth(store, { logout, refresh: { path: '/Account/RefreshToken' } });
|
|
70
|
+
* initUserAuth(store, { logout, refresh: { path: '/Account/RefreshToken' }, installationId: getOrCreateInstallationId });
|
|
63
71
|
*/
|
|
64
72
|
export declare const initUserAuth: <S>(store: S, options: UserAuthOptions) => void;
|
|
65
73
|
//# sourceMappingURL=initUserAuth.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class OutboxFullError extends Error {
|
|
2
|
+
constructor();
|
|
3
|
+
}
|
|
4
|
+
export declare class OutboxSignedOutError extends Error {
|
|
5
|
+
constructor();
|
|
6
|
+
}
|
|
7
|
+
export declare class OutboxMissingKeyError extends Error {
|
|
8
|
+
constructor();
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OutboxRequest } from "./types.js";
|
|
2
|
+
/** Copies each file part into Paths.document/webority-outbox/<entryId>/ and returns the request pointing at the copies; throws when a source is missing or empty (react-native.md 0-byte guard). */
|
|
3
|
+
export declare const persistRequestFiles: (entryId: string, request: OutboxRequest) => Promise<OutboxRequest>;
|
|
4
|
+
export declare const deleteEntryFiles: (entryId: string) => Promise<void>;
|
|
5
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
export type OutboxMethod = "POST" | "PUT" | "PATCH";
|
|
2
|
+
export interface OutboxFilePart {
|
|
3
|
+
uri: string;
|
|
4
|
+
name: string;
|
|
5
|
+
type: string;
|
|
6
|
+
}
|
|
7
|
+
export type OutboxFormField = {
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
} | {
|
|
11
|
+
name: string;
|
|
12
|
+
file: OutboxFilePart;
|
|
13
|
+
};
|
|
14
|
+
export type OutboxBody = {
|
|
15
|
+
kind: "json";
|
|
16
|
+
value: unknown;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "multipart";
|
|
19
|
+
fields: OutboxFormField[];
|
|
20
|
+
};
|
|
21
|
+
export interface OutboxRequest {
|
|
22
|
+
method: OutboxMethod;
|
|
23
|
+
/** As the http client takes it (relative to its base URL). */
|
|
24
|
+
url: string;
|
|
25
|
+
/** Must carry Idempotency-Key (a uuid); Authorization and Account-Id are refused, the outbox sets the workspace itself. */
|
|
26
|
+
headers: Record<string, string>;
|
|
27
|
+
body: OutboxBody;
|
|
28
|
+
timeoutMs?: number;
|
|
29
|
+
}
|
|
30
|
+
export type OutboxEntryState = "Pending" | "Sending" | "Failed";
|
|
31
|
+
export interface OutboxFailure {
|
|
32
|
+
code: string;
|
|
33
|
+
message: string;
|
|
34
|
+
status: number | null;
|
|
35
|
+
}
|
|
36
|
+
export interface OutboxEntry {
|
|
37
|
+
id: string;
|
|
38
|
+
queue: string;
|
|
39
|
+
/** Shown in lists: the ticket subject, the first words of a reply. */
|
|
40
|
+
label: string;
|
|
41
|
+
/** The request as it will be sent; file parts point at the outbox's own copies. */
|
|
42
|
+
request: OutboxRequest;
|
|
43
|
+
state: OutboxEntryState;
|
|
44
|
+
attempts: number;
|
|
45
|
+
lastFailure: OutboxFailure | null;
|
|
46
|
+
createdDateTimeUtc: string;
|
|
47
|
+
nextAttemptDateTimeUtc: string;
|
|
48
|
+
}
|
|
49
|
+
export type OutboxSendResult = {
|
|
50
|
+
status: "Sent";
|
|
51
|
+
entry: OutboxEntry;
|
|
52
|
+
httpStatus: number;
|
|
53
|
+
data: unknown;
|
|
54
|
+
} | {
|
|
55
|
+
status: "Queued";
|
|
56
|
+
entry: OutboxEntry;
|
|
57
|
+
} | {
|
|
58
|
+
status: "Failed";
|
|
59
|
+
entry: OutboxEntry;
|
|
60
|
+
failure: OutboxFailure;
|
|
61
|
+
};
|
|
62
|
+
export type OutboxEvent = {
|
|
63
|
+
type: "changed";
|
|
64
|
+
queue: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: "sent";
|
|
67
|
+
entry: OutboxEntry;
|
|
68
|
+
httpStatus: number;
|
|
69
|
+
data: unknown;
|
|
70
|
+
} | {
|
|
71
|
+
type: "failed";
|
|
72
|
+
entry: OutboxEntry;
|
|
73
|
+
};
|
|
74
|
+
export type OutboxListener = (event: OutboxEvent) => void;
|
|
75
|
+
/** The slice of the app's signed-in axios instance (mobile-core's userClient) the outbox sends through. */
|
|
76
|
+
export interface OutboxHttpClient {
|
|
77
|
+
request(config: {
|
|
78
|
+
method: string;
|
|
79
|
+
url: string;
|
|
80
|
+
headers: Record<string, string>;
|
|
81
|
+
data?: unknown;
|
|
82
|
+
timeout?: number;
|
|
83
|
+
retry?: false;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
status: number;
|
|
86
|
+
data: unknown;
|
|
87
|
+
}>;
|
|
88
|
+
}
|
|
89
|
+
export interface OutboxOptions {
|
|
90
|
+
http: OutboxHttpClient;
|
|
91
|
+
/** Default "webority-outbox". */
|
|
92
|
+
databaseName?: string;
|
|
93
|
+
/** Default 50; enqueue beyond it throws OutboxFullError. */
|
|
94
|
+
maxEntriesPerOwner?: number;
|
|
95
|
+
/** Default 14; older entries are deleted with their files. */
|
|
96
|
+
keepDays?: number;
|
|
97
|
+
}
|
|
98
|
+
export interface Outbox {
|
|
99
|
+
/** Stores the entry (files copied first), then tries it once. Definitive refusal on this first try deletes the entry and returns Failed. */
|
|
100
|
+
send(input: {
|
|
101
|
+
queue: string;
|
|
102
|
+
label: string;
|
|
103
|
+
request: OutboxRequest;
|
|
104
|
+
}): Promise<OutboxSendResult>;
|
|
105
|
+
/** The signed-in owner's entries of one queue, oldest first. */
|
|
106
|
+
list(queue: string): Promise<OutboxEntry[]>;
|
|
107
|
+
retry(id: string): Promise<OutboxSendResult>;
|
|
108
|
+
discard(id: string): Promise<void>;
|
|
109
|
+
/** Sends every due entry of the signed-in owner, one at a time, oldest first. */
|
|
110
|
+
flush(): Promise<void>;
|
|
111
|
+
subscribe(listener: OutboxListener): () => void;
|
|
112
|
+
/** Stops the listeners and timers (tests, hot reload). */
|
|
113
|
+
close(): Promise<void>;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -6,9 +6,14 @@ import { type ApiError } from "../errors/index.js";
|
|
|
6
6
|
*
|
|
7
7
|
* `silent` opts this call out of the error toast (decision 42); an endpoint can
|
|
8
8
|
* instead set it once for every call with `extraOptions: { silent: true }`.
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
9
|
+
* `expectedStatuses` lists the statuses the screen handles itself: a failure with
|
|
10
|
+
* one is logged at info, never recorded as an error. `public` sends the call
|
|
11
|
+
* through the anonymous client (sign-in, sign-up, a public lookup), so one
|
|
12
|
+
* `createApi` serves both clients. `paramsFormat` picks how a list in `params`
|
|
13
|
+
* reaches the query string; see `ParamsFormat`.
|
|
11
14
|
*/
|
|
15
|
+
/** `"repeat"` sends `a=1&a=2`, `"brackets"` sends `a[]=1&a[]=2`, `"comma"` sends `a=1,2`. */
|
|
16
|
+
export type ParamsFormat = "repeat" | "brackets" | "comma";
|
|
12
17
|
export interface ApiRequest {
|
|
13
18
|
url: string;
|
|
14
19
|
method?: Method;
|
|
@@ -21,12 +26,16 @@ export interface ApiRequest {
|
|
|
21
26
|
responseType?: Extract<ResponseType, "json" | "text">;
|
|
22
27
|
timeout?: number;
|
|
23
28
|
silent?: boolean;
|
|
29
|
+
expectedStatuses?: number[];
|
|
30
|
+
paramsFormat?: ParamsFormat;
|
|
24
31
|
public?: boolean;
|
|
25
32
|
}
|
|
26
33
|
export type ApiQueryArgs = string | ApiRequest;
|
|
27
34
|
/** Per-endpoint options, set as the endpoint's `extraOptions`. */
|
|
28
35
|
export interface ApiExtraOptions {
|
|
29
36
|
silent?: boolean;
|
|
37
|
+
expectedStatuses?: number[];
|
|
38
|
+
paramsFormat?: ParamsFormat;
|
|
30
39
|
}
|
|
31
40
|
/**
|
|
32
41
|
* Returned as the base query's `meta`, which RTK Query copies onto the
|
|
@@ -36,6 +45,8 @@ export interface ApiExtraOptions {
|
|
|
36
45
|
*/
|
|
37
46
|
export interface ApiBaseQueryMeta {
|
|
38
47
|
silent: boolean;
|
|
48
|
+
/** The statuses the call's screen handles itself; the toast middleware skips a failure with one. */
|
|
49
|
+
expectedStatuses?: number[];
|
|
39
50
|
/** The HTTP status, or 0 when no response arrived. */
|
|
40
51
|
status: number;
|
|
41
52
|
}
|
|
@@ -12,9 +12,13 @@ import { type ApiError } from "../errors/extractApiError.js";
|
|
|
12
12
|
* - an RTK Query endpoint: `extraOptions: { silent: true }`, which the base query copies
|
|
13
13
|
* onto its meta.
|
|
14
14
|
*
|
|
15
|
+
* An RTK Query call whose `expectedStatuses` holds the failure's status is never toasted, as
|
|
16
|
+
* with `silent`: the screen handles that status itself.
|
|
17
|
+
*
|
|
15
18
|
* Never toasted: an aborted thunk or a cancelled request (a screen unmounting), an RTK Query
|
|
16
19
|
* condition skip (the data is already cached), a 401 by default (the auth layer owns a dead
|
|
17
|
-
* session), a `workspace_changed` rejection (the request belonged to a workspace the user left)
|
|
20
|
+
* session), a `workspace_changed` rejection (the request belonged to a workspace the user left),
|
|
21
|
+
* a failure whose `fieldErrors` name a field (the form already shows each one inline).
|
|
18
22
|
* Identical messages are de-duplicated for `dedupeMs`, because a screen that fires
|
|
19
23
|
* four fetches and loses the network would otherwise stack four copies of one sentence.
|
|
20
24
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/mobile-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.124.0",
|
|
4
4
|
"description": "Platform layer for Webority React Native apps: HTTP clients, auth/token storage, config, logging, formatters, validators, network status, permissions, storage, version checks and over-the-air updates. No UI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -142,6 +142,16 @@
|
|
|
142
142
|
"default": "./lib/commonjs/sqlite/index.js"
|
|
143
143
|
}
|
|
144
144
|
},
|
|
145
|
+
"./outbox": {
|
|
146
|
+
"import": {
|
|
147
|
+
"types": "./lib/typescript/module/outbox/index.d.ts",
|
|
148
|
+
"default": "./lib/module/outbox/index.js"
|
|
149
|
+
},
|
|
150
|
+
"require": {
|
|
151
|
+
"types": "./lib/typescript/commonjs/outbox/index.d.ts",
|
|
152
|
+
"default": "./lib/commonjs/outbox/index.js"
|
|
153
|
+
}
|
|
154
|
+
},
|
|
145
155
|
"./download": {
|
|
146
156
|
"import": {
|
|
147
157
|
"types": "./lib/typescript/module/download/index.d.ts",
|
|
@@ -182,6 +192,16 @@
|
|
|
182
192
|
"default": "./lib/commonjs/share/index.js"
|
|
183
193
|
}
|
|
184
194
|
},
|
|
195
|
+
"./clipboard": {
|
|
196
|
+
"import": {
|
|
197
|
+
"types": "./lib/typescript/module/clipboard/index.d.ts",
|
|
198
|
+
"default": "./lib/module/clipboard/index.js"
|
|
199
|
+
},
|
|
200
|
+
"require": {
|
|
201
|
+
"types": "./lib/typescript/commonjs/clipboard/index.d.ts",
|
|
202
|
+
"default": "./lib/commonjs/clipboard/index.js"
|
|
203
|
+
}
|
|
204
|
+
},
|
|
185
205
|
"./review": {
|
|
186
206
|
"import": {
|
|
187
207
|
"types": "./lib/typescript/module/review/index.d.ts",
|
|
@@ -348,6 +368,7 @@
|
|
|
348
368
|
"expo-application": ">=57.0.0",
|
|
349
369
|
"expo-calendar": ">=57.0.0",
|
|
350
370
|
"expo-camera": ">=57.0.0",
|
|
371
|
+
"expo-clipboard": ">=57.0.0",
|
|
351
372
|
"expo-contacts": ">=57.0.0",
|
|
352
373
|
"expo-crypto": ">=57.0.0",
|
|
353
374
|
"expo-document-picker": ">=57.0.0",
|
|
@@ -380,6 +401,9 @@
|
|
|
380
401
|
"expo-camera": {
|
|
381
402
|
"optional": true
|
|
382
403
|
},
|
|
404
|
+
"expo-clipboard": {
|
|
405
|
+
"optional": true
|
|
406
|
+
},
|
|
383
407
|
"expo-contacts": {
|
|
384
408
|
"optional": true
|
|
385
409
|
},
|
|
@@ -465,6 +489,7 @@
|
|
|
465
489
|
"@webority/mobile-dev": "0.0.0",
|
|
466
490
|
"expo": "57.0.31",
|
|
467
491
|
"expo-application": "57.0.3",
|
|
492
|
+
"expo-clipboard": "57.0.2",
|
|
468
493
|
"expo-crypto": "57.0.4",
|
|
469
494
|
"expo-document-picker": "57.0.3",
|
|
470
495
|
"expo-file-system": "57.0.7",
|