@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,250 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.setFileSystemImplementation = exports.downloadFile = exports.DownloadError = void 0;
7
- var ExpoFileSystem = _interopRequireWildcard(require("expo-file-system"));
8
- var _reactNative = require("react-native");
9
- var _index = require("../logger/index.js");
10
- var _index2 = require("../permissions/index.js");
11
- var _expoFs = require("./adapters/expoFs.js");
12
- var _shared = require("./adapters/shared.js");
13
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
14
- const PREFIX = '[@webority/mobile-core]';
15
-
16
- /** Android stopped requiring a storage permission for a Downloads write at API 29. */
17
- const SCOPED_STORAGE_API_LEVEL = 29;
18
-
19
- /** A file can take far longer than the 30 s the fleet's JSON clients allow. */
20
- const DOWNLOAD_TIMEOUT_MS = 300000;
21
-
22
- /**
23
- * The slice of a filesystem module this module actually uses. expo-file-system
24
- * is adapted onto it, and a test or the showcase can inject its own with
25
- * `setFileSystemImplementation`.
26
- */
27
-
28
- /**
29
- * The slice of an HTTP client a download needs. The app's axios instance
30
- * (mobile-core's `userClient` or `publicClient`, or its own) satisfies it as is,
31
- * so whatever that client adds to a request (bearer token, tenant header, refresh
32
- * and retry on 401) applies to the download too. Declared structurally, as
33
- * mobile-support's client is, so no axios type leaks into the declarations.
34
- */
35
-
36
- class DownloadError extends Error {
37
- constructor(code, message, status) {
38
- super(`${PREFIX} ${message}`);
39
- this.name = 'DownloadError';
40
- this.code = code;
41
- this.status = status;
42
- // Babel's class transform can drop the prototype link, which makes
43
- // `instanceof DownloadError` false in the transpiled build.
44
- Object.setPrototypeOf(this, DownloadError.prototype);
45
- }
46
- }
47
- exports.DownloadError = DownloadError;
48
- const describe = error => error instanceof Error ? error.message : String(error);
49
-
50
- /** Only what a test or the showcase injected; null means use expo-file-system. */
51
- let backend = null;
52
-
53
- /**
54
- * expo-file-system, adapted once and memoised. The adapter is shape-checked, so
55
- * a build where the native module did not link returns null and the guided
56
- * error below still fires rather than a confusing property access.
57
- */
58
- let expoBackend;
59
- const resolveBackend = () => {
60
- if (backend) {
61
- return backend;
62
- }
63
- if (expoBackend === undefined) {
64
- expoBackend = (0, _expoFs.adaptExpoFileSystem)(ExpoFileSystem);
65
- }
66
- return expoBackend;
67
- };
68
-
69
- /**
70
- * Replace the filesystem backend. Intended for TESTS and for the showcase,
71
- * which injects a denying backend to demo the permission error; an app gets
72
- * expo-file-system without wiring anything. Pass `null` to restore it.
73
- */
74
- const setFileSystemImplementation = impl => {
75
- backend = impl;
76
- };
77
- exports.setFileSystemImplementation = setFileSystemImplementation;
78
- const requireBackend = () => {
79
- const fs = resolveBackend();
80
- if (!fs) {
81
- throw new DownloadError('unsupported', 'No filesystem module is available, so files cannot be downloaded. ' + 'expo-file-system did not load, which on a real build means the native module ' + 'was not linked.');
82
- }
83
- return fs;
84
- };
85
- const stripControlChars = value => Array.from(value).filter(char => (char.codePointAt(0) ?? 0) > 0x1f).join('');
86
- const lastSegment = raw => {
87
- const segments = raw.split(/[/\\]/);
88
- return stripControlChars(segments[segments.length - 1] ?? '').trim();
89
- };
90
-
91
- /**
92
- * Reduce a caller- or server-supplied name to a single path segment: `../../evil.pdf`
93
- * must land inside the destination directory as `evil.pdf` rather than escaping it.
94
- */
95
- const sanitiseFileName = raw => {
96
- const base = lastSegment(raw);
97
- if (base === '' || base === '.' || base === '..') {
98
- throw new DownloadError('write-failed', `"${raw}" does not contain a usable file name. Pass an explicit fileName.`);
99
- }
100
- return base;
101
- };
102
- const fileNameFromUrl = url => {
103
- const withoutQuery = url.split('#')[0]?.split('?')[0] ?? '';
104
- const last = withoutQuery.split('/').pop() ?? '';
105
- let decoded = last;
106
- try {
107
- decoded = decodeURIComponent(last);
108
- } catch {
109
- // A malformed escape sequence is not a reason to fail the download.
110
- }
111
- const base = lastSegment(decoded);
112
- return base === '' || base === '.' || base === '..' ? 'download' : base;
113
- };
114
- const androidApiLevel = () => typeof _reactNative.Platform.Version === 'number' ? _reactNative.Platform.Version : Number.parseInt(String(_reactNative.Platform.Version), 10);
115
- const ensureStoragePermission = async destination => {
116
- if (_reactNative.Platform.OS !== 'android' || destination !== 'downloads') {
117
- return;
118
- }
119
- if (androidApiLevel() >= SCOPED_STORAGE_API_LEVEL) {
120
- return;
121
- }
122
- const status = await _index2.Permissions.ensure('storage');
123
- if (status === 'granted' || status === 'limited') {
124
- return;
125
- }
126
- throw new DownloadError('permission-denied', `Storage permission is "${status}", so nothing can be written to the Downloads folder ` + 'on this Android version. Ask the user to grant it (Permissions.openSettings()), or ' + 'download to the "documents" destination instead.');
127
- };
128
- const emptyFile = url => new DownloadError('empty-file', `The download of ${url} produced an empty file, so nothing was saved. ` + 'Check that the URL is correct and that the request carried the credentials the ' + 'server expects.');
129
- const requestFailed = (error, options, fileName) => {
130
- if (options.signal?.aborted) {
131
- return new DownloadError('aborted', `The download of ${fileName} was aborted.`);
132
- }
133
- const e = error ?? {};
134
- // By name, not instanceof: a second copy of mobile-core would fail instanceof.
135
- if (e.name === 'RequestOfflineError') {
136
- return new DownloadError('network', `The device is offline, so ${options.url} was not downloaded.`);
137
- }
138
- const status = e.response?.status;
139
- if (typeof status === 'number') {
140
- return new DownloadError('http-error', `The server answered ${status} for ${options.url}, so no file was saved.`, status);
141
- }
142
- return new DownloadError('network', `The download of ${options.url} failed: ${describe(error)}`);
143
- };
144
- const discardPartial = async (fs, path) => {
145
- try {
146
- if (await fs.exists(path)) {
147
- await fs.unlink(path);
148
- }
149
- } catch (error) {
150
- _index.Logger.warn(`${PREFIX} Failed to remove the partial download at ${path}`, error);
151
- }
152
- };
153
-
154
- /**
155
- * Download a file to the device through the app's own HTTP client, so it is
156
- * authenticated exactly as the app's other calls are. The whole file is held
157
- * in memory before it is written, which suits documents and reports rather
158
- * than large media.
159
- *
160
- * A finished download is always verified to be non-empty: a 0-byte file looks
161
- * like a success to every caller and then wedges whatever consumes it, so it is
162
- * reported as `empty-file` and nothing is kept.
163
- */
164
- const downloadFile = async options => {
165
- const fs = requireBackend();
166
- const destination = options.destination ?? 'documents';
167
- const fileName = options.fileName ? sanitiseFileName(options.fileName) : fileNameFromUrl(options.url);
168
- await ensureStoragePermission(destination);
169
- const directory = fs.dirs[destination];
170
- const path = `${directory}/${fileName}`;
171
- if (options.signal?.aborted) {
172
- throw new DownloadError('aborted', `The download of ${fileName} was aborted before it started.`);
173
- }
174
- let reuseExisting = false;
175
- try {
176
- await fs.mkdir(directory);
177
- const exists = await fs.exists(path);
178
- if (exists && options.overwrite === false) {
179
- reuseExisting = true;
180
- } else if (exists) {
181
- await fs.unlink(path);
182
- }
183
- } catch (error) {
184
- throw new DownloadError('write-failed', `Could not prepare ${path} for writing: ${describe(error)}`);
185
- }
186
- if (reuseExisting) {
187
- const stat = await fs.stat(path);
188
- return {
189
- path,
190
- bytes: (0, _shared.asNumber)(stat?.size),
191
- mimeType: options.mimeType,
192
- fromCache: true
193
- };
194
- }
195
- const {
196
- onProgress
197
- } = options;
198
- let data;
199
- try {
200
- ({
201
- data
202
- } = await options.client.get(options.url, {
203
- headers: {
204
- Accept: '*/*',
205
- ...options.headers
206
- },
207
- responseType: 'arraybuffer',
208
- timeout: DOWNLOAD_TIMEOUT_MS,
209
- signal: options.signal,
210
- onDownloadProgress: onProgress ? ({
211
- loaded,
212
- total = 0
213
- }) => onProgress(loaded, total, total > 0 ? loaded / total : 0) : undefined
214
- }));
215
- } catch (error) {
216
- throw requestFailed(error, options, fileName);
217
- }
218
- if (options.signal?.aborted) {
219
- throw new DownloadError('aborted', `The download of ${fileName} was aborted.`);
220
- }
221
- const received = new Uint8Array(data ?? new ArrayBuffer(0));
222
- if (received.byteLength === 0) {
223
- throw emptyFile(options.url);
224
- }
225
- try {
226
- await fs.write(path, received);
227
- } catch (error) {
228
- await discardPartial(fs, path);
229
- throw new DownloadError('write-failed', `Could not write ${path}: ${describe(error)}`);
230
- }
231
- let bytes = 0;
232
- try {
233
- bytes = (await fs.exists(path)) ? (0, _shared.asNumber)((await fs.stat(path)).size) : 0;
234
- } catch (error) {
235
- await discardPartial(fs, path);
236
- throw new DownloadError('write-failed', `The download of ${fileName} finished but ${path} could not be read back: ${describe(error)}`);
237
- }
238
- if (bytes <= 0) {
239
- await discardPartial(fs, path);
240
- throw emptyFile(options.url);
241
- }
242
- return {
243
- path,
244
- bytes,
245
- mimeType: options.mimeType,
246
- fromCache: false
247
- };
248
- };
249
- exports.downloadFile = downloadFile;
250
- //# sourceMappingURL=index.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.setFileSystemImplementation=exports.downloadFile=exports.DownloadError=void 0;var ExpoFileSystem=_interopRequireWildcard(require("expo-file-system")),_reactNative=require("react-native"),_index=require("../logger/index.js"),_index2=require("../permissions/index.js"),_expoFs=require("./adapters/expoFs.js"),_shared=require("./adapters/shared.js");function _interopRequireWildcard(e,r){if("function"==typeof WeakMap)var t=new WeakMap,o=new WeakMap;return(_interopRequireWildcard=function(e,r){if(!r&&e&&e.__esModule)return e;var a,n,i={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return i;if(a=r?o:t){if(a.has(e))return a.get(e);a.set(e,i)}for(const r in e)"default"!==r&&{}.hasOwnProperty.call(e,r)&&((n=(a=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,r))&&(n.get||n.set)?a(i,r,n):i[r]=e[r]);return i})(e,r)}const PREFIX="[@webority/mobile-core]",SCOPED_STORAGE_API_LEVEL=29,DOWNLOAD_TIMEOUT_MS=3e5;class DownloadError extends Error{constructor(e,r,t){super(`${PREFIX} ${r}`),this.name="DownloadError",this.code=e,this.status=t,Object.setPrototypeOf(this,DownloadError.prototype)}}exports.DownloadError=DownloadError;const describe=e=>e instanceof Error?e.message:String(e);let expoBackend,backend=null;const resolveBackend=()=>backend||(void 0===expoBackend&&(expoBackend=(0,_expoFs.adaptExpoFileSystem)(ExpoFileSystem)),expoBackend),setFileSystemImplementation=e=>{backend=e};exports.setFileSystemImplementation=setFileSystemImplementation;const requireBackend=()=>{const e=resolveBackend();if(!e)throw new DownloadError("unsupported","No filesystem module is available, so files cannot be downloaded. expo-file-system did not load, which on a real build means the native module was not linked.");return e},stripControlChars=e=>Array.from(e).filter(e=>(e.codePointAt(0)??0)>31).join(""),lastSegment=e=>{const r=e.split(/[/\\]/);return stripControlChars(r[r.length-1]??"").trim()},sanitiseFileName=e=>{const r=lastSegment(e);if(""===r||"."===r||".."===r)throw new DownloadError("write-failed",`"${e}" does not contain a usable file name. Pass an explicit fileName.`);return r},fileNameFromUrl=e=>{const r=(e.split("#")[0]?.split("?")[0]??"").split("/").pop()??"";let t=r;try{t=decodeURIComponent(r)}catch{}const o=lastSegment(t);return""===o||"."===o||".."===o?"download":o},androidApiLevel=()=>"number"==typeof _reactNative.Platform.Version?_reactNative.Platform.Version:Number.parseInt(String(_reactNative.Platform.Version),10),ensureStoragePermission=async e=>{if("android"!==_reactNative.Platform.OS||"downloads"!==e)return;if(androidApiLevel()>=29)return;const r=await _index2.Permissions.ensure("storage");if("granted"!==r&&"limited"!==r)throw new DownloadError("permission-denied",`Storage permission is "${r}", so nothing can be written to the Downloads folder on this Android version. Ask the user to grant it (Permissions.openSettings()), or download to the "documents" destination instead.`)},emptyFile=e=>new DownloadError("empty-file",`The download of ${e} produced an empty file, so nothing was saved. Check that the URL is correct and that the request carried the credentials the server expects.`),requestFailed=(e,r,t)=>{if(r.signal?.aborted)return new DownloadError("aborted",`The download of ${t} was aborted.`);const o=e??{};if("RequestOfflineError"===o.name)return new DownloadError("network",`The device is offline, so ${r.url} was not downloaded.`);const a=o.response?.status;return"number"==typeof a?new DownloadError("http-error",`The server answered ${a} for ${r.url}, so no file was saved.`,a):new DownloadError("network",`The download of ${r.url} failed: ${describe(e)}`)},discardPartial=async(e,r)=>{try{await e.exists(r)&&await e.unlink(r)}catch(e){_index.Logger.warn(`${PREFIX} Failed to remove the partial download at ${r}`,e)}},downloadFile=async e=>{const r=requireBackend(),t=e.destination??"documents",o=e.fileName?sanitiseFileName(e.fileName):fileNameFromUrl(e.url);await ensureStoragePermission(t);const a=r.dirs[t],n=`${a}/${o}`;if(e.signal?.aborted)throw new DownloadError("aborted",`The download of ${o} was aborted before it started.`);let i=!1;try{await r.mkdir(a);const t=await r.exists(n);t&&!1===e.overwrite?i=!0:t&&await r.unlink(n)}catch(e){throw new DownloadError("write-failed",`Could not prepare ${n} for writing: ${describe(e)}`)}if(i){const t=await r.stat(n);return{path:n,bytes:(0,_shared.asNumber)(t?.size),mimeType:e.mimeType,fromCache:!0}}const{onProgress:s}=e;let d;try{({data:d}=await e.client.get(e.url,{headers:{Accept:"*/*",...e.headers},responseType:"arraybuffer",timeout:3e5,signal:e.signal,onDownloadProgress:s?({loaded:e,total:r=0})=>s(e,r,r>0?e/r:0):void 0}))}catch(r){throw requestFailed(r,e,o)}if(e.signal?.aborted)throw new DownloadError("aborted",`The download of ${o} was aborted.`);const l=new Uint8Array(d??new ArrayBuffer(0));if(0===l.byteLength)throw emptyFile(e.url);try{await r.write(n,l)}catch(e){throw await discardPartial(r,n),new DownloadError("write-failed",`Could not write ${n}: ${describe(e)}`)}let c=0;try{c=await r.exists(n)?(0,_shared.asNumber)((await r.stat(n)).size):0}catch(e){throw await discardPartial(r,n),new DownloadError("write-failed",`The download of ${o} finished but ${n} could not be read back: ${describe(e)}`)}if(c<=0)throw await discardPartial(r,n),emptyFile(e.url);return{path:n,bytes:c,mimeType:e.mimeType,fromCache:!1}};exports.downloadFile=downloadFile;
@@ -1,70 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.formatCurrency = void 0;
7
- var _intlCache = require("./intlCache.js");
8
- const hasIntlNumber = () => typeof Intl !== 'undefined' && typeof Intl.NumberFormat === 'function';
9
- const indianGroupingFallback = (n, fractionDigits) => {
10
- // Indian numbering: 1,23,45,678.90 (last 3 digits, then groups of 2).
11
- const sign = n < 0 ? '-' : '';
12
- const abs = Math.abs(n);
13
- const fixed = abs.toFixed(fractionDigits);
14
- const [intPart, decPart] = fixed.split('.');
15
- const last3 = intPart.length > 3 ? intPart.slice(-3) : intPart;
16
- const rest = intPart.length > 3 ? intPart.slice(0, -3) : '';
17
- const grouped = rest ? rest.replace(/\B(?=(\d{2})+(?!\d))/g, ',') + ',' + last3 : last3;
18
- return sign + grouped + (decPart ? `.${decPart}` : '');
19
- };
20
-
21
- /**
22
- * Format an amount as currency. Defaults to **INR** with Indian numbering (`en-IN`),
23
- * which matches the standard convention across Webority projects.
24
- *
25
- * @example
26
- * formatCurrency(150000) // ₹1,50,000
27
- * formatCurrency(1234.5) // ₹1,234.50
28
- * formatCurrency(99, { currency: 'USD', locale: 'en-US' }) // $99.00
29
- * formatCurrency(150000, { stripSymbol: true }) // 1,50,000
30
- */
31
- const formatCurrency = (amount, options = {}) => {
32
- if (amount == null || Number.isNaN(amount)) {
33
- return '';
34
- }
35
- const {
36
- currency = 'INR',
37
- locale = 'en-IN',
38
- minimumFractionDigits,
39
- maximumFractionDigits = 2,
40
- stripSymbol = false
41
- } = options;
42
- const minFrac = minimumFractionDigits ?? (Number.isInteger(amount) ? 0 : 2);
43
- if (hasIntlNumber()) {
44
- try {
45
- const formatted = (0, _intlCache.numberFormat)(locale, {
46
- style: 'currency',
47
- currency,
48
- minimumFractionDigits: minFrac,
49
- maximumFractionDigits
50
- }).format(amount);
51
- if (!stripSymbol) {
52
- return formatted;
53
- }
54
- // Strip currency code/symbol while keeping digits, separators and sign.
55
- return formatted.replace(/[^\d,.\s\-+]/g, '').trim();
56
- } catch {
57
- /* fall through to fallback */
58
- }
59
- }
60
- const numeric = indianGroupingFallback(amount, minFrac);
61
- if (stripSymbol) {
62
- return numeric;
63
- }
64
- if (currency === 'INR') {
65
- return `₹${numeric}`;
66
- }
67
- return `${currency} ${numeric}`;
68
- };
69
- exports.formatCurrency = formatCurrency;
70
- //# sourceMappingURL=currency.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatCurrency=void 0;var _intlCache=require("./intlCache.js");const hasIntlNumber=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.NumberFormat,indianGroupingFallback=(r,t)=>{const e=r<0?"-":"",n=Math.abs(r).toFixed(t),[i,c]=n.split("."),a=i.length>3?i.slice(-3):i,o=i.length>3?i.slice(0,-3):"";return e+(o?o.replace(/\B(?=(\d{2})+(?!\d))/g,",")+","+a:a)+(c?`.${c}`:"")},formatCurrency=(r,t={})=>{if(null==r||Number.isNaN(r))return"";const{currency:e="INR",locale:n="en-IN",minimumFractionDigits:i,maximumFractionDigits:c=2,stripSymbol:a=!1}=t,o=i??(Number.isInteger(r)?0:2);if(hasIntlNumber())try{const t=(0,_intlCache.numberFormat)(n,{style:"currency",currency:e,minimumFractionDigits:o,maximumFractionDigits:c}).format(r);return a?t.replace(/[^\d,.\s\-+]/g,"").trim():t}catch{}const u=indianGroupingFallback(r,o);return a?u:"INR"===e?`₹${u}`:`${e} ${u}`};exports.formatCurrency=formatCurrency;
@@ -1,167 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.formatTime = exports.formatRelativeTime = exports.formatDateTime = exports.formatDate = void 0;
7
- var _intlCache = require("./intlCache.js");
8
- const toDate = value => {
9
- if (value instanceof Date) {
10
- return Number.isNaN(value.getTime()) ? null : value;
11
- }
12
- const d = new Date(value);
13
- return Number.isNaN(d.getTime()) ? null : d;
14
- };
15
- const hasIntl = () => typeof Intl !== 'undefined' && typeof Intl.DateTimeFormat === 'function';
16
- const PAD = n => n < 10 ? `0${n}` : `${n}`;
17
- const fallbackDate = (d, style) => {
18
- const day = PAD(d.getDate());
19
- const monthShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][d.getMonth()];
20
- const monthLong = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][d.getMonth()];
21
- const year = d.getFullYear();
22
- const weekdayLong = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][d.getDay()];
23
- switch (style) {
24
- case 'short':
25
- return `${day}/${PAD(d.getMonth() + 1)}/${year}`;
26
- case 'long':
27
- return `${day} ${monthLong} ${year}`;
28
- case 'full':
29
- return `${weekdayLong}, ${day} ${monthLong} ${year}`;
30
- case 'medium':
31
- default:
32
- return `${day} ${monthShort} ${year}`;
33
- }
34
- };
35
- const fallbackTime = (d, style) => {
36
- const hh = PAD(d.getHours());
37
- const mm = PAD(d.getMinutes());
38
- if (style === 'short') {
39
- return `${hh}:${mm}`;
40
- }
41
- const ss = PAD(d.getSeconds());
42
- return `${hh}:${mm}:${ss}`;
43
- };
44
-
45
- /**
46
- * Locale-aware date formatter. Defaults to `'medium'` style and `'en-IN'` locale,
47
- * matching the Indian-locale convention used across Webority apps.
48
- */
49
- const formatDate = (value, style = 'medium', locale = 'en-IN') => {
50
- const d = toDate(value);
51
- if (!d) {
52
- return '';
53
- }
54
- if (hasIntl()) {
55
- try {
56
- return (0, _intlCache.dateTimeFormat)(locale, {
57
- dateStyle: style
58
- }).format(d);
59
- } catch {
60
- /* fall through to fallback */
61
- }
62
- }
63
- return fallbackDate(d, style);
64
- };
65
-
66
- /**
67
- * Locale-aware time formatter (24-hour fallback when Intl is unavailable).
68
- */
69
- exports.formatDate = formatDate;
70
- const formatTime = (value, style = 'short', locale = 'en-IN') => {
71
- const d = toDate(value);
72
- if (!d) {
73
- return '';
74
- }
75
- if (hasIntl()) {
76
- try {
77
- return (0, _intlCache.dateTimeFormat)(locale, {
78
- timeStyle: style
79
- }).format(d);
80
- } catch {
81
- /* fall through */
82
- }
83
- }
84
- return fallbackTime(d, style);
85
- };
86
-
87
- /**
88
- * Combined date + time formatter.
89
- */
90
- exports.formatTime = formatTime;
91
- const formatDateTime = (value, dateStyle = 'medium', timeStyle = 'short', locale = 'en-IN') => {
92
- const d = toDate(value);
93
- if (!d) {
94
- return '';
95
- }
96
- if (hasIntl()) {
97
- try {
98
- return (0, _intlCache.dateTimeFormat)(locale, {
99
- dateStyle,
100
- timeStyle
101
- }).format(d);
102
- } catch {
103
- /* fall through */
104
- }
105
- }
106
- return `${fallbackDate(d, dateStyle)}, ${fallbackTime(d, timeStyle)}`;
107
- };
108
- exports.formatDateTime = formatDateTime;
109
- const SECOND = 1000;
110
- const MINUTE = 60 * SECOND;
111
- const HOUR = 60 * MINUTE;
112
- const DAY = 24 * HOUR;
113
- const WEEK = 7 * DAY;
114
- const MONTH = 30 * DAY;
115
- const YEAR = 365 * DAY;
116
-
117
- /**
118
- * Returns a humanized relative-time string (e.g. "5 minutes ago", "in 3 days").
119
- * Uses `Intl.RelativeTimeFormat` when available; otherwise a sensible English fallback.
120
- */
121
- const formatRelativeTime = (value, base = new Date(), locale = 'en-IN') => {
122
- const target = toDate(value);
123
- const now = toDate(base);
124
- if (!target || !now) {
125
- return '';
126
- }
127
- const diffMs = target.getTime() - now.getTime();
128
- const abs = Math.abs(diffMs);
129
- let unit;
130
- let amount;
131
- if (abs < MINUTE) {
132
- unit = 'second';
133
- amount = Math.round(diffMs / SECOND);
134
- } else if (abs < HOUR) {
135
- unit = 'minute';
136
- amount = Math.round(diffMs / MINUTE);
137
- } else if (abs < DAY) {
138
- unit = 'hour';
139
- amount = Math.round(diffMs / HOUR);
140
- } else if (abs < WEEK) {
141
- unit = 'day';
142
- amount = Math.round(diffMs / DAY);
143
- } else if (abs < MONTH) {
144
- unit = 'week';
145
- amount = Math.round(diffMs / WEEK);
146
- } else if (abs < YEAR) {
147
- unit = 'month';
148
- amount = Math.round(diffMs / MONTH);
149
- } else {
150
- unit = 'year';
151
- amount = Math.round(diffMs / YEAR);
152
- }
153
- const Rtf = hasIntl() ? Intl.RelativeTimeFormat : undefined;
154
- if (typeof Rtf === 'function') {
155
- try {
156
- return (0, _intlCache.relativeTimeFormat)(Rtf, locale).format(amount, unit);
157
- } catch {
158
- /* fall through */
159
- }
160
- }
161
- const past = amount < 0;
162
- const n = Math.abs(amount);
163
- const u = n === 1 ? unit : `${unit}s`;
164
- return past ? `${n} ${u} ago` : `in ${n} ${u}`;
165
- };
166
- exports.formatRelativeTime = formatRelativeTime;
167
- //# sourceMappingURL=date.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.formatTime=exports.formatRelativeTime=exports.formatDateTime=exports.formatDate=void 0;var _intlCache=require("./intlCache.js");const toDate=t=>{if(t instanceof Date)return Number.isNaN(t.getTime())?null:t;const e=new Date(t);return Number.isNaN(e.getTime())?null:e},hasIntl=()=>"undefined"!=typeof Intl&&"function"==typeof Intl.DateTimeFormat,PAD=t=>t<10?`0${t}`:`${t}`,fallbackDate=(t,e)=>{const a=PAD(t.getDate()),r=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"][t.getMonth()],o=["January","February","March","April","May","June","July","August","September","October","November","December"][t.getMonth()],n=t.getFullYear(),i=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][t.getDay()];switch(e){case"short":return`${a}/${PAD(t.getMonth()+1)}/${n}`;case"long":return`${a} ${o} ${n}`;case"full":return`${i}, ${a} ${o} ${n}`;default:return`${a} ${r} ${n}`}},fallbackTime=(t,e)=>{const a=PAD(t.getHours()),r=PAD(t.getMinutes());if("short"===e)return`${a}:${r}`;return`${a}:${r}:${PAD(t.getSeconds())}`},formatDate=(t,e="medium",a="en-IN")=>{const r=toDate(t);if(!r)return"";if(hasIntl())try{return(0,_intlCache.dateTimeFormat)(a,{dateStyle:e}).format(r)}catch{}return fallbackDate(r,e)};exports.formatDate=formatDate;const formatTime=(t,e="short",a="en-IN")=>{const r=toDate(t);if(!r)return"";if(hasIntl())try{return(0,_intlCache.dateTimeFormat)(a,{timeStyle:e}).format(r)}catch{}return fallbackTime(r,e)};exports.formatTime=formatTime;const formatDateTime=(t,e="medium",a="short",r="en-IN")=>{const o=toDate(t);if(!o)return"";if(hasIntl())try{return(0,_intlCache.dateTimeFormat)(r,{dateStyle:e,timeStyle:a}).format(o)}catch{}return`${fallbackDate(o,e)}, ${fallbackTime(o,a)}`};exports.formatDateTime=formatDateTime;const SECOND=1e3,MINUTE=6e4,HOUR=36e5,DAY=24*HOUR,WEEK=7*DAY,MONTH=30*DAY,YEAR=365*DAY,formatRelativeTime=(t,e=new Date,a="en-IN")=>{const r=toDate(t),o=toDate(e);if(!r||!o)return"";const n=r.getTime()-o.getTime(),i=Math.abs(n);let m,u;i<6e4?(m="second",u=Math.round(n/1e3)):i<HOUR?(m="minute",u=Math.round(n/6e4)):i<DAY?(m="hour",u=Math.round(n/HOUR)):i<WEEK?(m="day",u=Math.round(n/DAY)):i<MONTH?(m="week",u=Math.round(n/WEEK)):i<YEAR?(m="month",u=Math.round(n/MONTH)):(m="year",u=Math.round(n/YEAR));const s=hasIntl()?Intl.RelativeTimeFormat:void 0;if("function"==typeof s)try{return(0,_intlCache.relativeTimeFormat)(s,a).format(u,m)}catch{}const l=u<0,c=Math.abs(u),f=1===c?m:`${m}s`;return l?`${c} ${f} ago`:`in ${c} ${f}`};exports.formatRelativeTime=formatRelativeTime;