@webority/mobile-core 0.0.29 → 0.1.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.
Files changed (139) hide show
  1. package/lib/commonjs/api/baseUrl.js +1 -34
  2. package/lib/commonjs/api/curl.js +1 -109
  3. package/lib/commonjs/api/multipart.js +1 -21
  4. package/lib/commonjs/api/publicClient.js +1 -79
  5. package/lib/commonjs/api/responseBodyText.js +1 -0
  6. package/lib/commonjs/api/retry.js +1 -91
  7. package/lib/commonjs/api/tokenRefresh.js +1 -205
  8. package/lib/commonjs/api/userClient.js +1 -265
  9. package/lib/commonjs/auth/authStore.js +1 -265
  10. package/lib/commonjs/auth/index.js +1 -44
  11. package/lib/commonjs/auth/jwt.js +1 -112
  12. package/lib/commonjs/config/index.js +1 -72
  13. package/lib/commonjs/deepLink/index.js +1 -286
  14. package/lib/commonjs/download/adapters/expoFs.js +1 -69
  15. package/lib/commonjs/download/adapters/shared.js +1 -13
  16. package/lib/commonjs/download/index.js +1 -250
  17. package/lib/commonjs/formatters/currency.js +1 -70
  18. package/lib/commonjs/formatters/date.js +1 -167
  19. package/lib/commonjs/formatters/dateMath.js +1 -311
  20. package/lib/commonjs/formatters/index.js +1 -246
  21. package/lib/commonjs/formatters/initials.js +1 -32
  22. package/lib/commonjs/formatters/intlCache.js +1 -37
  23. package/lib/commonjs/formatters/number.js +1 -89
  24. package/lib/commonjs/formatters/phone.js +1 -369
  25. package/lib/commonjs/formatters/windowsToIanaTable.js +1 -164
  26. package/lib/commonjs/geolocation/adapters/expoLocation.js +1 -126
  27. package/lib/commonjs/geolocation/index.js +1 -355
  28. package/lib/commonjs/index.js +1 -644
  29. package/lib/commonjs/initSDK.js +1 -66
  30. package/lib/commonjs/initUserAuth.js +1 -37
  31. package/lib/commonjs/logger/crashlytics.js +1 -0
  32. package/lib/commonjs/logger/index.js +1 -301
  33. package/lib/commonjs/logger/redact.js +1 -50
  34. package/lib/commonjs/network/index.js +1 -31
  35. package/lib/commonjs/network/networkStatus.js +1 -171
  36. package/lib/commonjs/permissions/calendar.js +1 -14
  37. package/lib/commonjs/permissions/camera.js +1 -14
  38. package/lib/commonjs/permissions/contacts.js +1 -10
  39. package/lib/commonjs/permissions/index.js +1 -133
  40. package/lib/commonjs/permissions/location.js +1 -14
  41. package/lib/commonjs/permissions/mediaLibrary.js +1 -10
  42. package/lib/commonjs/permissions/notifications.js +1 -10
  43. package/lib/commonjs/permissions/photos.js +1 -14
  44. package/lib/commonjs/phone/countries.js +1 -265
  45. package/lib/commonjs/push/index.js +1 -61
  46. package/lib/commonjs/push/push.js +1 -468
  47. package/lib/commonjs/push/status.js +1 -0
  48. package/lib/commonjs/push/task.js +1 -43
  49. package/lib/commonjs/secureScreen/index.js +1 -0
  50. package/lib/commonjs/share/index.js +1 -70
  51. package/lib/commonjs/smsRetriever/index.js +1 -91
  52. package/lib/commonjs/specs/NativeSmsRetriever.js +1 -15
  53. package/lib/commonjs/sqlite/adapters/expo.js +1 -53
  54. package/lib/commonjs/sqlite/index.js +1 -604
  55. package/lib/commonjs/storage/index.js +1 -214
  56. package/lib/commonjs/types/axios.js +1 -4
  57. package/lib/commonjs/types/globals.d.js +1 -6
  58. package/lib/commonjs/utils/base64.js +1 -24
  59. package/lib/commonjs/utils/imageCompression.js +1 -389
  60. package/lib/commonjs/utils/index.js +1 -19
  61. package/lib/commonjs/validators/index.js +1 -227
  62. package/lib/commonjs/versionCheck/index.js +1 -419
  63. package/lib/module/api/baseUrl.js +1 -30
  64. package/lib/module/api/curl.js +1 -104
  65. package/lib/module/api/multipart.js +1 -16
  66. package/lib/module/api/publicClient.js +1 -75
  67. package/lib/module/api/responseBodyText.js +1 -0
  68. package/lib/module/api/retry.js +1 -85
  69. package/lib/module/api/tokenRefresh.js +1 -192
  70. package/lib/module/api/userClient.js +1 -243
  71. package/lib/module/auth/authStore.js +1 -257
  72. package/lib/module/auth/index.js +1 -5
  73. package/lib/module/auth/jwt.js +1 -106
  74. package/lib/module/config/index.js +1 -64
  75. package/lib/module/deepLink/index.js +1 -280
  76. package/lib/module/download/adapters/expoFs.js +1 -64
  77. package/lib/module/download/adapters/shared.js +1 -8
  78. package/lib/module/download/index.js +1 -242
  79. package/lib/module/formatters/currency.js +1 -65
  80. package/lib/module/formatters/date.js +1 -159
  81. package/lib/module/formatters/dateMath.js +1 -295
  82. package/lib/module/formatters/index.js +1 -9
  83. package/lib/module/formatters/initials.js +1 -27
  84. package/lib/module/formatters/intlCache.js +1 -30
  85. package/lib/module/formatters/number.js +1 -82
  86. package/lib/module/formatters/phone.js +1 -302
  87. package/lib/module/formatters/windowsToIanaTable.js +1 -160
  88. package/lib/module/geolocation/adapters/expoLocation.js +1 -121
  89. package/lib/module/geolocation/index.js +1 -347
  90. package/lib/module/index.js +1 -57
  91. package/lib/module/initSDK.js +1 -61
  92. package/lib/module/initUserAuth.js +1 -33
  93. package/lib/module/logger/crashlytics.js +1 -0
  94. package/lib/module/logger/index.js +1 -295
  95. package/lib/module/logger/redact.js +1 -44
  96. package/lib/module/network/index.js +1 -4
  97. package/lib/module/network/networkStatus.js +1 -161
  98. package/lib/module/permissions/calendar.js +1 -15
  99. package/lib/module/permissions/camera.js +1 -15
  100. package/lib/module/permissions/contacts.js +1 -11
  101. package/lib/module/permissions/index.js +1 -128
  102. package/lib/module/permissions/location.js +1 -15
  103. package/lib/module/permissions/mediaLibrary.js +1 -11
  104. package/lib/module/permissions/notifications.js +1 -11
  105. package/lib/module/permissions/photos.js +1 -15
  106. package/lib/module/phone/countries.js +1 -261
  107. package/lib/module/push/index.js +1 -4
  108. package/lib/module/push/push.js +1 -452
  109. package/lib/module/push/status.js +1 -0
  110. package/lib/module/push/task.js +1 -38
  111. package/lib/module/secureScreen/index.js +1 -0
  112. package/lib/module/share/index.js +1 -64
  113. package/lib/module/smsRetriever/index.js +1 -86
  114. package/lib/module/specs/NativeSmsRetriever.js +1 -13
  115. package/lib/module/sqlite/adapters/expo.js +1 -48
  116. package/lib/module/sqlite/index.js +1 -594
  117. package/lib/module/storage/index.js +1 -208
  118. package/lib/module/types/axios.js +1 -4
  119. package/lib/module/types/globals.d.js +1 -10
  120. package/lib/module/utils/base64.js +1 -19
  121. package/lib/module/utils/imageCompression.js +1 -383
  122. package/lib/module/utils/index.js +1 -4
  123. package/lib/module/validators/index.js +1 -205
  124. package/lib/module/versionCheck/index.js +1 -413
  125. package/lib/typescript/commonjs/api/responseBodyText.d.ts +6 -0
  126. package/lib/typescript/commonjs/index.d.ts +5 -0
  127. package/lib/typescript/commonjs/logger/crashlytics.d.ts +31 -0
  128. package/lib/typescript/commonjs/push/index.d.ts +3 -1
  129. package/lib/typescript/commonjs/push/push.d.ts +1 -1
  130. package/lib/typescript/commonjs/push/status.d.ts +9 -0
  131. package/lib/typescript/commonjs/secureScreen/index.d.ts +25 -0
  132. package/lib/typescript/module/api/responseBodyText.d.ts +6 -0
  133. package/lib/typescript/module/index.d.ts +5 -0
  134. package/lib/typescript/module/logger/crashlytics.d.ts +31 -0
  135. package/lib/typescript/module/push/index.d.ts +3 -1
  136. package/lib/typescript/module/push/push.d.ts +1 -1
  137. package/lib/typescript/module/push/status.d.ts +9 -0
  138. package/lib/typescript/module/secureScreen/index.d.ts +25 -0
  139. package/package.json +23 -4
@@ -1,121 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * The slice of expo-location this adapter uses. Verified against 57.0.14.
5
- *
6
- * The REQUIRE lives in the entry point beside this file, never here.
7
- */
8
-
9
- /**
10
- * expo-location's Accuracy enum is numeric (`Balanced = 3`, `Highest = 5`,
11
- * verified in Location.types.d.ts). The numbers are inlined rather than
12
- * imported so this file names no expo module and stays bundlable by an app
13
- * without expo installed.
14
- */
15
- const ACCURACY_BALANCED = 3;
16
- const ACCURACY_HIGHEST = 5;
17
- const toExpoOptions = options => {
18
- const expo = {
19
- accuracy: options?.enableHighAccuracy ? ACCURACY_HIGHEST : ACCURACY_BALANCED
20
- };
21
- if (typeof options?.distanceFilter === 'number') {
22
- expo.distanceInterval = options.distanceFilter;
23
- }
24
- return expo;
25
- };
26
-
27
- /**
28
- * expo-location rejects with an Error; the seam expects the W3C-style numeric
29
- * codes the RN geolocation modules use, which the library then maps to its own
30
- * GeolocationError kinds. Classifying here rather than passing the raw Error
31
- * through is what makes an expo-backed app produce the same `permission-denied`
32
- * / `services-disabled` / `timeout` values as a NetInfo-backed one — which is
33
- * the whole point of having a seam.
34
- */
35
- const PERMISSION_PATTERN = /permission|denied|not (been )?granted|authoriz/i;
36
- const SERVICES_PATTERN = /location services|provider|disabled|switched off|turned off/i;
37
- const TIMEOUT_PATTERN = /time ?d? ?out|timeout/i;
38
- const toNativeError = raw => {
39
- const message = raw instanceof Error ? raw.message : String(raw);
40
- if (PERMISSION_PATTERN.test(message)) {
41
- return {
42
- code: 1,
43
- message
44
- };
45
- }
46
- if (TIMEOUT_PATTERN.test(message)) {
47
- return {
48
- code: 3,
49
- message
50
- };
51
- }
52
- // Code 2 covers both "services off" and "no fix". The library separates them
53
- // by reading the message, so the message must travel intact — and where expo
54
- // does not say "location services", the wording is normalised so it can.
55
- if (SERVICES_PATTERN.test(message)) {
56
- return {
57
- code: 2,
58
- message
59
- };
60
- }
61
- return {
62
- code: 2,
63
- message
64
- };
65
- };
66
- const toNativePosition = location => ({
67
- coords: {
68
- latitude: location.coords?.latitude ?? null,
69
- longitude: location.coords?.longitude ?? null,
70
- accuracy: location.coords?.accuracy ?? null,
71
- altitude: location.coords?.altitude ?? null,
72
- heading: location.coords?.heading ?? null,
73
- speed: location.coords?.speed ?? null
74
- },
75
- timestamp: location.timestamp ?? null
76
- });
77
-
78
- /**
79
- * Adapts expo-location to the library's geolocation seam.
80
- *
81
- * The interesting half is `watchPosition`. The seam must hand back a numeric
82
- * watch id SYNCHRONOUSLY, while `watchPositionAsync` only resolves its
83
- * subscription later. So the adapter mints its own id immediately and stores
84
- * the subscription against it on arrival. `clearWatch` called during that
85
- * window records the id as cancelled, and the subscription is removed the
86
- * moment it lands — without that, a screen that unmounts before the watch
87
- * starts leaks a live GPS listener for the rest of the session, which is a
88
- * battery drain nobody would attribute to this code.
89
- */
90
- export const adaptExpoLocation = mod => {
91
- const subscriptions = new Map();
92
- let nextWatchId = 1;
93
- return {
94
- getCurrentPosition: (onSuccess, onError, options) => {
95
- mod.getCurrentPositionAsync(toExpoOptions(options)).then(location => onSuccess(toNativePosition(location))).catch(error => onError?.(toNativeError(error)));
96
- },
97
- watchPosition: (onSuccess, onError, options) => {
98
- const watchId = nextWatchId++;
99
- subscriptions.set(watchId, null);
100
- mod.watchPositionAsync(toExpoOptions(options), location => onSuccess(toNativePosition(location))).then(subscription => {
101
- if (!subscriptions.has(watchId)) {
102
- // clearWatch already ran. Remove immediately rather than storing a
103
- // subscription nothing will ever clear.
104
- subscription.remove();
105
- return;
106
- }
107
- subscriptions.set(watchId, subscription);
108
- }).catch(error => {
109
- subscriptions.delete(watchId);
110
- onError?.(toNativeError(error));
111
- });
112
- return watchId;
113
- },
114
- clearWatch: watchId => {
115
- const subscription = subscriptions.get(watchId);
116
- subscriptions.delete(watchId);
117
- subscription?.remove();
118
- }
119
- };
120
- };
121
- //# sourceMappingURL=expoLocation.js.map
1
+ const toExpoOptions=e=>{const t={accuracy:e?.enableHighAccuracy?5:3};return"number"==typeof e?.distanceFilter&&(t.distanceInterval=e.distanceFilter),t},e=/permission|denied|not (been )?granted|authoriz/i,t=/location services|provider|disabled|switched off|turned off/i,o=/time ?d? ?out|timeout/i,toNativeError=n=>{const s=n instanceof Error?n.message:String(n);return e.test(s)?{code:1,message:s}:o.test(s)?{code:3,message:s}:(t.test(s),{code:2,message:s})},toNativePosition=e=>({coords:{latitude:e.coords?.latitude??null,longitude:e.coords?.longitude??null,accuracy:e.coords?.accuracy??null,altitude:e.coords?.altitude??null,heading:e.coords?.heading??null,speed:e.coords?.speed??null},timestamp:e.timestamp??null});export const adaptExpoLocation=e=>{const t=new Map;let o=1;return{getCurrentPosition:(t,o,n)=>{e.getCurrentPositionAsync(toExpoOptions(n)).then(e=>t(toNativePosition(e))).catch(e=>o?.(toNativeError(e)))},watchPosition:(n,s,c)=>{const r=o++;return t.set(r,null),e.watchPositionAsync(toExpoOptions(c),e=>n(toNativePosition(e))).then(e=>{t.has(r)?t.set(r,e):e.remove()}).catch(e=>{t.delete(r),s?.(toNativeError(e))}),r},clearWatch:e=>{const o=t.get(e);t.delete(e),o?.remove()}}};
@@ -1,347 +1 @@
1
- "use strict";
2
-
3
- import * as ExpoLocation from 'expo-location';
4
- import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { Logger } from "../logger/index.js";
6
- import { Permissions } from "../permissions/index.js";
7
- // expo-location is a REQUIRED peer (unlike the other Expo permission
8
- // packages, which are optional and registered only when an app opts in by
9
- // importing their own entry point) — anything that reaches this module
10
- // already forces Metro to resolve expo-location, so self-registering its
11
- // permission kinds here costs nothing extra and makes Geolocation's
12
- // permission gating work without a separate app-level import.
13
- import "../permissions/location.js";
14
- import { adaptExpoLocation } from "./adapters/expoLocation.js";
15
- const PREFIX = '[@webority/mobile-core]';
16
- export class GeolocationError extends Error {
17
- constructor(code, message) {
18
- super(message);
19
- this.name = 'GeolocationError';
20
- this.code = code;
21
- // Babel downlevels `class extends Error`, which breaks `instanceof` for
22
- // subclasses unless the prototype is restored explicitly.
23
- Object.setPrototypeOf(this, GeolocationError.prototype);
24
- }
25
- }
26
-
27
- /** Minimal shape of the native geolocation module we depend on. */
28
-
29
- const DEFAULT_TIMEOUT_MS = 15000;
30
- const DEFAULT_RETRIES = 1;
31
- const DEFAULT_RETRY_DELAY_MS = 800;
32
-
33
- /** Only what a test or the showcase injected; null means use expo-location. */
34
- let backend = null;
35
-
36
- /**
37
- * expo-location is a required peer, so the JS module always resolves. What can
38
- * be missing is the NATIVE side: an app that installed the package without
39
- * running the native install gets a module whose calls are absent. Checking the
40
- * two the adapter needs is what lets `isAvailable` mean something and makes the
41
- * error below reachable.
42
- *
43
- * An INJECTED backend is taken on trust, like every other seam in this package.
44
- */
45
- const hasNativeLocation = mod => typeof mod?.getCurrentPositionAsync === 'function' && typeof mod?.watchPositionAsync === 'function';
46
- let expoBackend;
47
- const resolveBackend = () => {
48
- if (backend) {
49
- return backend;
50
- }
51
- if (expoBackend === undefined) {
52
- const mod = ExpoLocation;
53
- expoBackend = hasNativeLocation(mod) ? adaptExpoLocation(mod) : null;
54
- }
55
- return expoBackend;
56
- };
57
-
58
- /**
59
- * Replace the geolocation provider. Intended for TESTS and for the showcase,
60
- * which injects a denying provider to demo the permission and services-off
61
- * errors; an app gets expo-location without wiring anything. Pass `null` to
62
- * restore it.
63
- */
64
- export const setGeolocationImplementation = impl => {
65
- backend = impl;
66
- };
67
- const requireBackend = op => {
68
- const b = resolveBackend();
69
- if (!b) {
70
- throw new GeolocationError('unsupported', `${PREFIX} No geolocation provider is available; cannot ${op}. ` + 'expo-location did not load, which on a real build means the native ' + 'module was not linked.');
71
- }
72
- return b;
73
- };
74
-
75
- /**
76
- * Android reports "location services are switched off" through the same code 2
77
- * that also covers a genuine failure to fix a position, and the two need
78
- * different handling: one is fixed by the user in system settings, the other is
79
- * worth retrying. The message is the only signal that separates them.
80
- */
81
- const SERVICES_OFF_PATTERN = /(location|gps)[^.]{0,40}(disabled|switched off|turned off|not enabled)|no location provider|settings_not_satisfied|location services (are |is )?off/i;
82
- const toGeoError = raw => {
83
- if (raw instanceof GeolocationError) {
84
- return raw;
85
- }
86
- const native = raw ?? {};
87
- const detail = typeof native.message === 'string' && native.message.length > 0 ? native.message : 'the provider gave no reason';
88
- switch (native.code) {
89
- case 1:
90
- return new GeolocationError('permission-denied', `${PREFIX} Location permission was denied (${detail}). Request the ` + 'location permission before calling, or send the user to settings.');
91
- case 2:
92
- return SERVICES_OFF_PATTERN.test(detail) ? new GeolocationError('services-disabled', `${PREFIX} Location services are switched off (${detail}). Ask the user ` + 'to enable location in system settings; retrying will not help.') : new GeolocationError('position-unavailable', `${PREFIX} No position fix (${detail}).`);
93
- case 3:
94
- return new GeolocationError('timeout', `${PREFIX} Location request timed out (${detail}).`);
95
- case 4:
96
- case 5:
97
- return new GeolocationError('services-disabled', `${PREFIX} Location services are unavailable on this device (${detail}). ` + 'Ask the user to enable location, or install Google Play services.');
98
- default:
99
- return new GeolocationError('position-unavailable', `${PREFIX} Location request failed (${detail}).`);
100
- }
101
- };
102
- const RETRYABLE = ['timeout', 'position-unavailable'];
103
- const normalizeCoords = raw => {
104
- const coords = raw?.coords;
105
- if (!coords || !Number.isFinite(coords.latitude) || !Number.isFinite(coords.longitude)) {
106
- return null;
107
- }
108
- return {
109
- latitude: coords.latitude,
110
- longitude: coords.longitude,
111
- // An absent radius is treated as infinitely bad rather than perfect, so a
112
- // provider that omits it can never satisfy `minimumAccuracyM` by accident.
113
- accuracy: Number.isFinite(coords.accuracy) ? coords.accuracy : Number.POSITIVE_INFINITY,
114
- altitude: Number.isFinite(coords.altitude) ? coords.altitude : null,
115
- heading: Number.isFinite(coords.heading) ? coords.heading : null,
116
- speed: Number.isFinite(coords.speed) ? coords.speed : null
117
- };
118
- };
119
- const normalizePosition = raw => {
120
- const coords = normalizeCoords(raw);
121
- if (!coords) {
122
- return null;
123
- }
124
- return {
125
- coords,
126
- timestamp: Number.isFinite(raw?.timestamp) ? raw?.timestamp : Date.now()
127
- };
128
- };
129
- const toNativeOptions = options => {
130
- const native = {
131
- enableHighAccuracy: (options.accuracy ?? 'fine') === 'fine',
132
- timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
133
- maximumAge: options.maximumAgeMs ?? 0
134
- };
135
- if (options.distanceFilterM !== undefined) {
136
- native.distanceFilter = options.distanceFilterM;
137
- }
138
- return native;
139
- };
140
- const sleep = ms => new Promise(resolve => {
141
- setTimeout(resolve, ms);
142
- });
143
- const ensureLocationPermission = async () => {
144
- const status = await Permissions.ensure('location');
145
- if (status === 'granted' || status === 'limited') {
146
- return;
147
- }
148
- if (status === 'unavailable') {
149
- Logger.warn(`${PREFIX} Location permission status is unavailable (expo-location is not installed, ` + 'or the check failed); attempting the location request anyway.');
150
- return;
151
- }
152
- throw new GeolocationError('permission-denied', `${PREFIX} Location permission is "${status}". Grant it before requesting a position` + (status === 'blocked' ? ', or call Permissions.openSettings() to let the user fix it.' : '.'));
153
- };
154
- const positionOnce = (b, options) => {
155
- const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
156
- return new Promise((resolve, reject) => {
157
- let settled = false;
158
- // The native timeout is passed through as well, but a provider that never
159
- // calls back at all would otherwise hang the caller forever.
160
- const timer = setTimeout(() => {
161
- if (settled) {
162
- return;
163
- }
164
- settled = true;
165
- reject(new GeolocationError('timeout', `${PREFIX} Location request timed out after ${timeoutMs}ms. Raise timeoutMs, or use ` + "accuracy: 'coarse' where a network fix is good enough."));
166
- }, timeoutMs);
167
- const settle = run => {
168
- if (settled) {
169
- return;
170
- }
171
- settled = true;
172
- clearTimeout(timer);
173
- run();
174
- };
175
- const onSuccess = raw => settle(() => {
176
- const position = normalizePosition(raw);
177
- if (!position) {
178
- reject(new GeolocationError('position-unavailable', `${PREFIX} The provider returned a fix without usable coordinates.`));
179
- return;
180
- }
181
- const floor = options.minimumAccuracyM;
182
- if (floor !== undefined && position.coords.accuracy > floor) {
183
- reject(new GeolocationError('position-unavailable', `${PREFIX} Fix accuracy ${position.coords.accuracy}m is worse than the required ` + `${floor}m.`));
184
- return;
185
- }
186
- resolve(position);
187
- });
188
- const onError = error => settle(() => reject(toGeoError(error)));
189
- try {
190
- b.getCurrentPosition(onSuccess, onError, toNativeOptions(options));
191
- } catch (error) {
192
- settle(() => reject(toGeoError(error)));
193
- }
194
- });
195
- };
196
- const getCurrentPosition = async (options = {}) => {
197
- const b = requireBackend('get the current position');
198
- await ensureLocationPermission();
199
- const attempts = Math.max(0, Math.trunc(options.retries ?? DEFAULT_RETRIES)) + 1;
200
- const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
201
- let lastError = null;
202
- for (let attempt = 0; attempt < attempts; attempt += 1) {
203
- try {
204
- return await positionOnce(b, options);
205
- } catch (error) {
206
- const geoError = toGeoError(error);
207
- if (!RETRYABLE.includes(geoError.code)) {
208
- throw geoError;
209
- }
210
- lastError = geoError;
211
- if (attempt < attempts - 1 && retryDelayMs > 0) {
212
- await sleep(retryDelayMs);
213
- }
214
- }
215
- }
216
- throw lastError ?? new GeolocationError('position-unavailable', `${PREFIX} Location request failed.`);
217
- };
218
- const watchPosition = (listener, options = {}) => {
219
- const b = requireBackend('watch the position');
220
- let cancelled = false;
221
- let watchId = null;
222
- const stop = () => {
223
- if (cancelled) {
224
- return;
225
- }
226
- cancelled = true;
227
- if (watchId !== null) {
228
- b.clearWatch(watchId);
229
- watchId = null;
230
- }
231
- };
232
- const fail = error => {
233
- const geoError = toGeoError(error);
234
- Logger.error(geoError.message);
235
- options.onError?.(geoError);
236
- };
237
- void ensureLocationPermission().then(() => {
238
- // The caller can unsubscribe while the permission gate is still pending;
239
- // registering afterwards would leak a watch nothing can clear.
240
- if (cancelled) {
241
- return;
242
- }
243
- watchId = b.watchPosition(raw => {
244
- if (cancelled) {
245
- return;
246
- }
247
- const position = normalizePosition(raw);
248
- if (!position) {
249
- return;
250
- }
251
- const floor = options.minimumAccuracyM;
252
- if (floor !== undefined && position.coords.accuracy > floor) {
253
- return;
254
- }
255
- listener(position);
256
- }, error => {
257
- if (!cancelled) {
258
- fail(error);
259
- }
260
- }, toNativeOptions(options));
261
- }).catch(fail);
262
- return stop;
263
- };
264
- const isAvailable = () => resolveBackend() !== null;
265
- export const Geolocation = {
266
- getCurrentPosition,
267
- watchPosition,
268
- isAvailable
269
- };
270
- export const useCurrentPosition = (options = {}) => {
271
- const {
272
- enabled = true,
273
- accuracy,
274
- timeoutMs,
275
- maximumAgeMs,
276
- retries,
277
- minimumAccuracyM,
278
- retryDelayMs
279
- } = options;
280
- const [state, setState] = useState({
281
- position: null,
282
- error: null,
283
- loading: enabled
284
- });
285
- const mountedRef = useRef(true);
286
- // Identifies the in-flight request so a slow earlier fix cannot overwrite the
287
- // result of a later refresh().
288
- const requestRef = useRef(0);
289
- useEffect(() => {
290
- mountedRef.current = true;
291
- return () => {
292
- mountedRef.current = false;
293
- };
294
- }, []);
295
-
296
- // Every dependency is a primitive read off `options`, so an inline options
297
- // object (the normal call shape) does not re-create this on every render.
298
- const run = useCallback(() => {
299
- requestRef.current += 1;
300
- const token = requestRef.current;
301
- setState(prev => prev.loading ? prev : {
302
- ...prev,
303
- loading: true
304
- });
305
- const accept = next => {
306
- if (mountedRef.current && requestRef.current === token) {
307
- setState(next);
308
- }
309
- };
310
- getCurrentPosition({
311
- accuracy,
312
- timeoutMs,
313
- maximumAgeMs,
314
- retries,
315
- minimumAccuracyM,
316
- retryDelayMs
317
- }).then(position => accept({
318
- position,
319
- error: null,
320
- loading: false
321
- }), error => accept({
322
- position: null,
323
- error: toGeoError(error),
324
- loading: false
325
- }));
326
- }, [accuracy, timeoutMs, maximumAgeMs, retries, minimumAccuracyM, retryDelayMs]);
327
- useEffect(() => {
328
- if (!enabled) {
329
- // Discard any in-flight request so its result cannot land after opting out.
330
- requestRef.current += 1;
331
- setState(prev => prev.loading || prev.position !== null || prev.error !== null ? {
332
- position: null,
333
- error: null,
334
- loading: false
335
- } : prev);
336
- return;
337
- }
338
- run();
339
- }, [enabled, run]);
340
- return {
341
- position: state.position,
342
- error: state.error,
343
- loading: state.loading,
344
- refresh: run
345
- };
346
- };
347
- //# sourceMappingURL=index.js.map
1
+ import*as e from"expo-location";import{useCallback as o,useEffect as t,useRef as i,useState as r}from"react";import{Logger as n}from"../logger/index.js";import{Permissions as s}from"../permissions/index.js";import"../permissions/location.js";import{adaptExpoLocation as a}from"./adapters/expoLocation.js";const c="[@webority/mobile-core]";export class GeolocationError extends Error{constructor(e,o){super(o),this.name="GeolocationError",this.code=e,Object.setPrototypeOf(this,GeolocationError.prototype)}}let l=null;let u;const resolveBackend=()=>{if(l)return l;if(void 0===u){const o=e;u=(e=>"function"==typeof e?.getCurrentPositionAsync&&"function"==typeof e?.watchPositionAsync)(o)?a(o):null}return u};export const setGeolocationImplementation=e=>{l=e};const requireBackend=e=>{const o=resolveBackend();if(!o)throw new GeolocationError("unsupported",`${c} No geolocation provider is available; cannot ${e}. expo-location did not load, which on a real build means the native module was not linked.`);return o},d=/(location|gps)[^.]{0,40}(disabled|switched off|turned off|not enabled)|no location provider|settings_not_satisfied|location services (are |is )?off/i,toGeoError=e=>{if(e instanceof GeolocationError)return e;const o=e??{},t="string"==typeof o.message&&o.message.length>0?o.message:"the provider gave no reason";switch(o.code){case 1:return new GeolocationError("permission-denied",`${c} Location permission was denied (${t}). Request the location permission before calling, or send the user to settings.`);case 2:return d.test(t)?new GeolocationError("services-disabled",`${c} Location services are switched off (${t}). Ask the user to enable location in system settings; retrying will not help.`):new GeolocationError("position-unavailable",`${c} No position fix (${t}).`);case 3:return new GeolocationError("timeout",`${c} Location request timed out (${t}).`);case 4:case 5:return new GeolocationError("services-disabled",`${c} Location services are unavailable on this device (${t}). Ask the user to enable location, or install Google Play services.`);default:return new GeolocationError("position-unavailable",`${c} Location request failed (${t}).`)}},m=["timeout","position-unavailable"],normalizePosition=e=>{const o=(e=>{const o=e?.coords;return o&&Number.isFinite(o.latitude)&&Number.isFinite(o.longitude)?{latitude:o.latitude,longitude:o.longitude,accuracy:Number.isFinite(o.accuracy)?o.accuracy:Number.POSITIVE_INFINITY,altitude:Number.isFinite(o.altitude)?o.altitude:null,heading:Number.isFinite(o.heading)?o.heading:null,speed:Number.isFinite(o.speed)?o.speed:null}:null})(e);return o?{coords:o,timestamp:Number.isFinite(e?.timestamp)?e?.timestamp:Date.now()}:null},toNativeOptions=e=>{const o={enableHighAccuracy:"fine"===(e.accuracy??"fine"),timeout:e.timeoutMs??15e3,maximumAge:e.maximumAgeMs??0};return void 0!==e.distanceFilterM&&(o.distanceFilter=e.distanceFilterM),o},sleep=e=>new Promise(o=>{setTimeout(o,e)}),ensureLocationPermission=async()=>{const e=await s.ensure("location");if("granted"!==e&&"limited"!==e){if("unavailable"!==e)throw new GeolocationError("permission-denied",`${c} Location permission is "${e}". Grant it before requesting a position`+("blocked"===e?", or call Permissions.openSettings() to let the user fix it.":"."));n.warn(`${c} Location permission status is unavailable (expo-location is not installed, or the check failed); attempting the location request anyway.`)}},positionOnce=(e,o)=>{const t=o.timeoutMs??15e3;return new Promise((i,r)=>{let n=!1;const s=setTimeout(()=>{n||(n=!0,r(new GeolocationError("timeout",`${c} Location request timed out after ${t}ms. Raise timeoutMs, or use accuracy: 'coarse' where a network fix is good enough.`)))},t),settle=e=>{n||(n=!0,clearTimeout(s),e())},onSuccess=e=>settle(()=>{const t=normalizePosition(e);if(!t)return void r(new GeolocationError("position-unavailable",`${c} The provider returned a fix without usable coordinates.`));const n=o.minimumAccuracyM;void 0!==n&&t.coords.accuracy>n?r(new GeolocationError("position-unavailable",`${c} Fix accuracy ${t.coords.accuracy}m is worse than the required ${n}m.`)):i(t)}),onError=e=>settle(()=>r(toGeoError(e)));try{e.getCurrentPosition(onSuccess,onError,toNativeOptions(o))}catch(e){settle(()=>r(toGeoError(e)))}})},getCurrentPosition=async(e={})=>{const o=requireBackend("get the current position");await ensureLocationPermission();const t=Math.max(0,Math.trunc(e.retries??1))+1,i=e.retryDelayMs??800;let r=null;for(let n=0;n<t;n+=1)try{return await positionOnce(o,e)}catch(e){const o=toGeoError(e);if(!m.includes(o.code))throw o;r=o,n<t-1&&i>0&&await sleep(i)}throw r??new GeolocationError("position-unavailable",`${c} Location request failed.`)};export const Geolocation={getCurrentPosition:getCurrentPosition,watchPosition:(e,o={})=>{const t=requireBackend("watch the position");let i=!1,r=null;const fail=e=>{const t=toGeoError(e);n.error(t.message),o.onError?.(t)};return ensureLocationPermission().then(()=>{i||(r=t.watchPosition(t=>{if(i)return;const r=normalizePosition(t);if(!r)return;const n=o.minimumAccuracyM;void 0!==n&&r.coords.accuracy>n||e(r)},e=>{i||fail(e)},toNativeOptions(o)))}).catch(fail),()=>{i||(i=!0,null!==r&&(t.clearWatch(r),r=null))}},isAvailable:()=>null!==resolveBackend()};export const useCurrentPosition=(e={})=>{const{enabled:n=!0,accuracy:s,timeoutMs:a,maximumAgeMs:c,retries:l,minimumAccuracyM:u,retryDelayMs:d}=e,[m,p]=r({position:null,error:null,loading:n}),h=i(!0),f=i(0);t(()=>(h.current=!0,()=>{h.current=!1}),[]);const g=o(()=>{f.current+=1;const e=f.current;p(e=>e.loading?e:{...e,loading:!0});const accept=o=>{h.current&&f.current===e&&p(o)};getCurrentPosition({accuracy:s,timeoutMs:a,maximumAgeMs:c,retries:l,minimumAccuracyM:u,retryDelayMs:d}).then(e=>accept({position:e,error:null,loading:!1}),e=>accept({position:null,error:toGeoError(e),loading:!1}))},[s,a,c,l,u,d]);return t(()=>{if(!n)return f.current+=1,void p(e=>e.loading||null!==e.position||null!==e.error?{position:null,error:null,loading:!1}:e);g()},[n,g]),{position:m.position,error:m.error,loading:m.loading,refresh:g}};
@@ -1,57 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * The main barrel deliberately does NOT re-export the modules that need a native
5
- * package. Metro resolves requires statically, so anything reachable from here
6
- * is resolved for every consumer, which would make an optional peer mandatory
7
- * for anyone importing anything at all. Those live behind their own import
8
- * paths instead:
9
- *
10
- * @webority/mobile-core/permissions per kind, its own Expo module
11
- * @webority/mobile-core/compressor expo-image-manipulator + expo-file-system
12
- * @webority/mobile-core/geolocation a geolocation provider
13
- * @webority/mobile-core/sqlite expo-sqlite
14
- * @webority/mobile-core/download a filesystem module
15
- * @webority/mobile-core/share expo-sharing
16
- * @webority/mobile-core/smsRetriever Android only, own TurboModule
17
- *
18
- * One more path is separate for size, not for a native package:
19
- *
20
- * @webority/mobile-core/phone/countries 245 English country names
21
- *
22
- * Token storage is the exception and IS on the main barrel, because the HTTP
23
- * client reads the bearer token. It needs no optional peer: the backend is
24
- * expo-secure-store, and `expo` is required anyway.
25
- */
26
- // API clients
27
- export { buildCurl, logCurl } from "./api/curl.js";
28
- export { default as publicClient } from "./api/publicClient.js";
29
- export { attachRetry, isRetryableStatus } from "./api/retry.js";
30
- export { refreshAccessToken } from "./api/tokenRefresh.js";
31
- export { default as userClient, injectStore, injectUserAuth, RequestOfflineError, resetRefreshState, SESSION_TERMINATION_CODES } from "./api/userClient.js";
32
- // Auth / token storage
33
- export { ACCESS_TOKEN_KEY, getToken, REFRESH_TOKEN_KEY, removeToken, setKeychainImplementation, storeToken } from "./auth/authStore.js";
34
- export { decodeJWT, getJWTExpiry, isJWTExpired } from "./auth/jwt.js";
35
- // Configuration
36
- export { getConfig, getConfigValue, resetConfig, setConfig } from "./config/index.js";
37
- // Deep links
38
- export { DeepLink, parseDeepLink, useDeepLink } from "./deepLink/index.js";
39
- // Formatters
40
- export { AsYouType, addDays, clampNationalNumber, countryFlagEmoji, detectPhoneCountry, diffMs, formatCompactNumber, formatCurrency, formatDate, formatDateDDMMMYYYY, formatDateISO, formatDatePattern, formatDateTime, formatNumber, formatPercent, formatPhone, formatPhoneAsTyped, formatRelativeTime, formatTime, formatTime12h, formatTimeInWindowsZone, formatTimeInZone, getCountries, getCountryCallingCode, getInitials, getPhoneCountries, isDateAfter, isDateBefore, isSameDay, isSupportedCountry, isValidNationalNumber, isValidPhoneNumber, maxNationalNumberLength, normalizePhone, parsePhoneNumber, parsePhoneNumberFromString, splitPhoneNumber, startOfDay, validatePhoneNumberLength } from "./formatters/index.js";
41
- // Initialization
42
- export { initWebority } from "./initSDK.js";
43
- export { initUserAuth } from "./initUserAuth.js";
44
- // Logger
45
- export { configureLogger, getDeviceContext, Logger, setDeviceContext, setRemoteLogger } from "./logger/index.js";
46
- // Network status (the NetworkStatusBanner UI lives in @webority/mobile-ui)
47
- export { addNetworkStatusListener, getNetworkStatus, setNetworkStatusImplementation, useNetworkStatus } from "./network/index.js";
48
- // Storage: the API and the seam. No native package is required; wire one with
49
- // setStorageImplementation to get persistence.
50
- export { isStorageAvailable, Storage, setStorageImplementation } from "./storage/index.js";
51
- // Bytes
52
- export { encodeBase64 } from "./utils/base64.js";
53
- // Validators
54
- export { isAadhaar, isAlphanumeric, isBetween, isEmail, isGstin, isHexColor, isIfsc, isIndianMobile, isIndianPincode, isInteger, isNonEmpty, isNumeric, isPan, isPhone, isStrongPassword, isUrl, maxLength, minLength } from "./validators/index.js";
55
- // Version check (the ForceUpdateDialog UI lives in @webority/mobile-ui)
56
- export { setDeviceInfoImplementation, useVersionCheck, VersionCheck } from "./versionCheck/index.js";
57
- //# sourceMappingURL=index.js.map
1
+ export{buildCurl,logCurl}from"./api/curl.js";export{default as publicClient}from"./api/publicClient.js";export{attachRetry,isRetryableStatus}from"./api/retry.js";export{refreshAccessToken}from"./api/tokenRefresh.js";export{default as userClient,injectStore,injectUserAuth,RequestOfflineError,resetRefreshState,SESSION_TERMINATION_CODES}from"./api/userClient.js";export{ACCESS_TOKEN_KEY,getToken,REFRESH_TOKEN_KEY,removeToken,setKeychainImplementation,storeToken}from"./auth/authStore.js";export{decodeJWT,getJWTExpiry,isJWTExpired}from"./auth/jwt.js";export{getConfig,getConfigValue,resetConfig,setConfig}from"./config/index.js";export{DeepLink,parseDeepLink,useDeepLink}from"./deepLink/index.js";export{AsYouType,addDays,clampNationalNumber,countryFlagEmoji,detectPhoneCountry,diffMs,formatCompactNumber,formatCurrency,formatDate,formatDateDDMMMYYYY,formatDateISO,formatDatePattern,formatDateTime,formatNumber,formatPercent,formatPhone,formatPhoneAsTyped,formatRelativeTime,formatTime,formatTime12h,formatTimeInWindowsZone,formatTimeInZone,getCountries,getCountryCallingCode,getInitials,getPhoneCountries,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,setRemoteLogger}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{setDeviceInfoImplementation,useVersionCheck,VersionCheck}from"./versionCheck/index.js";
@@ -1,61 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Simple initialization API for Webority packages
5
- * One function to configure everything needed
6
- */
7
-
8
- import { setKeychainImplementation } from "./auth/authStore.js";
9
- import { DEFAULT_LOG_LEVEL, setConfig } from "./config/index.js";
10
- import { Logger } from "./logger/index.js";
11
- import { setNetworkStatusImplementation } from "./network/networkStatus.js";
12
- import { setStorageImplementation } from "./storage/index.js";
13
- /**
14
- * Initialize Webority packages with your project configuration.
15
- *
16
- * @example
17
- * // Basic setup
18
- * initWebority({
19
- * baseUrl: 'https://api.myapp.com'
20
- * });
21
- *
22
- * @example
23
- * // Full configuration
24
- * initWebority({
25
- * baseUrl: 'https://api.myapp.com',
26
- * loggingEnabled: __DEV__,
27
- * logLevel: 'warn',
28
- * environment: __DEV__ ? 'Development' : 'Production'
29
- * });
30
- */
31
- export const initWebority = config => {
32
- if (!config.baseUrl) {
33
- throw new Error('baseUrl is required for Webority packages initialization');
34
- }
35
- setConfig({
36
- baseUrl: config.baseUrl,
37
- loggingEnabled: config.loggingEnabled ?? true,
38
- logLevel: config.logLevel || DEFAULT_LOG_LEVEL,
39
- environment: config.environment || 'Development',
40
- country: (config.country || 'in').toLowerCase(),
41
- appId: config.appId ?? null,
42
- appVersion: config.appVersion ?? null,
43
- logCurl: config.logCurl ?? false
44
- });
45
-
46
- // Only what the caller actually passed is wired. Calling a setter with
47
- // `undefined` would reset a backend an app had already injected by hand,
48
- // which is why each is guarded rather than passed straight through.
49
- const backends = config.backends;
50
- if (backends?.storage) {
51
- setStorageImplementation(backends.storage);
52
- }
53
- if (backends?.keychain) {
54
- setKeychainImplementation(backends.keychain);
55
- }
56
- if (backends?.network) {
57
- setNetworkStatusImplementation(backends.network);
58
- }
59
- Logger.info('[@webority/mobile-core] initialized');
60
- };
61
- //# sourceMappingURL=initSDK.js.map
1
+ import{setKeychainImplementation as o}from"./auth/authStore.js";import{DEFAULT_LOG_LEVEL as e,setConfig as r}from"./config/index.js";import{Logger as i}from"./logger/index.js";import{setNetworkStatusImplementation as n}from"./network/networkStatus.js";import{setStorageImplementation as t}from"./storage/index.js";export const initWebority=a=>{if(!a.baseUrl)throw new Error("baseUrl is required for Webority packages initialization");r({baseUrl:a.baseUrl,loggingEnabled:a.loggingEnabled??!0,logLevel:a.logLevel||e,environment:a.environment||"Development",country:(a.country||"in").toLowerCase(),appId:a.appId??null,appVersion:a.appVersion??null,logCurl:a.logCurl??!1});const l=a.backends;l?.storage&&t(l.storage),l?.keychain&&o(l.keychain),l?.network&&n(l.network),i.info("[@webority/mobile-core] initialized")};
@@ -1,33 +1 @@
1
- "use strict";
2
-
3
- import { injectStore, injectUserAuth } from "./api/userClient.js";
4
- import { Logger } from "./logger/index.js";
5
-
6
- /** The tokens a refresh response carries, with their expiry timestamps. */
7
-
8
- /**
9
- * How the library calls the app's refresh endpoint. The call goes through
10
- * `publicClient`, and the new tokens are stored under the library's own keys.
11
- */
12
-
13
- /**
14
- * Wire the user client to the app: the Redux store it dispatches `logout` to,
15
- * and the refresh endpoint it calls when an access token expires or a request
16
- * answers 401. Only a 400 or 401 from that endpoint, or a missing or expired
17
- * refresh token, logs out; a network error, timeout or 5xx keeps the session.
18
- *
19
- * @example
20
- * initUserAuth(store, { logout, refresh: { path: '/Account/RefreshToken' } });
21
- */
22
- export const initUserAuth = (store, options) => {
23
- if (!store) {
24
- throw new Error('Redux store is required for user package initialization');
25
- }
26
- if (!options.logout || !options.refresh?.path) {
27
- throw new Error('initUserAuth needs a logout action and refresh.path');
28
- }
29
- injectStore(store);
30
- injectUserAuth(options);
31
- Logger.info('[@webority/mobile-core] user auth wired to the store');
32
- };
33
- //# sourceMappingURL=initUserAuth.js.map
1
+ import{injectStore as r,injectUserAuth as e}from"./api/userClient.js";import{Logger as o}from"./logger/index.js";export const initUserAuth=(t,i)=>{if(!t)throw new Error("Redux store is required for user package initialization");if(!i.logout||!i.refresh?.path)throw new Error("initUserAuth needs a logout action and refresh.path");r(t),e(i),o.info("[@webority/mobile-core] user auth wired to the store")};
@@ -0,0 +1 @@
1
+ const describe=r=>{try{return JSON.stringify(r)}catch{return String(r)}};export const crashlyticsRemoteLogger=r=>{const send=t=>{try{const e=t(r.getCrashlytics());e&&"function"==typeof e.catch&&e.catch(()=>{})}catch{}};return{breadcrumb:(t,e)=>send(o=>r.log(o,e?`${t} ${describe(e)}`:t)),recordError:(t,e)=>{e&&send(t=>r.log(t,`context ${describe(e)}`)),send(e=>{return r.recordError(e,(o=t)instanceof Error?o:new Error(String(o)));var o})},setUser:t=>send(e=>r.setUserId(e,t??"")),setAttribute:(t,e)=>send(o=>r.setAttribute(o,t,null===e?"":String(e))),log:(t,e)=>send(o=>r.log(o,`[${t.toUpperCase()}] ${e}`))}};