expensify-common 2.0.188 → 2.0.190

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 (78) hide show
  1. package/dist/Logger.js +11 -1
  2. package/dist/esm/API.d.ts +11 -0
  3. package/dist/esm/API.js +786 -0
  4. package/dist/esm/APIDeferred.d.ts +7 -0
  5. package/dist/esm/APIDeferred.js +216 -0
  6. package/dist/esm/BrowserDetect.d.ts +19 -0
  7. package/dist/esm/BrowserDetect.js +105 -0
  8. package/dist/esm/CLI.js +37 -29
  9. package/dist/esm/CONST.d.ts +1727 -0
  10. package/dist/esm/CONST.js +1847 -0
  11. package/dist/esm/Cookie.d.ts +68 -0
  12. package/dist/esm/Cookie.js +159 -0
  13. package/dist/esm/CredentialsWrapper.d.ts +32 -0
  14. package/dist/esm/CredentialsWrapper.js +46 -0
  15. package/dist/esm/Device.d.ts +8 -0
  16. package/dist/esm/Device.js +24 -0
  17. package/dist/esm/ExpenseRule.d.ts +39 -0
  18. package/dist/esm/ExpenseRule.js +77 -0
  19. package/dist/esm/ExpensiMark.d.ts +197 -0
  20. package/dist/esm/ExpensiMark.js +1374 -0
  21. package/dist/esm/Func.d.ts +40 -0
  22. package/dist/esm/Func.js +69 -0
  23. package/dist/esm/Log.d.ts +3 -0
  24. package/dist/esm/Log.js +35 -0
  25. package/dist/esm/Logger.d.ts +82 -0
  26. package/dist/esm/Logger.js +148 -0
  27. package/dist/esm/Network.d.ts +6 -0
  28. package/dist/esm/Network.js +168 -0
  29. package/dist/esm/Num.d.ts +95 -0
  30. package/dist/esm/Num.js +190 -0
  31. package/dist/esm/PageEvent.d.ts +25 -0
  32. package/dist/esm/PageEvent.js +22 -0
  33. package/dist/esm/PubSub.d.ts +2 -0
  34. package/dist/esm/PubSub.js +111 -0
  35. package/dist/esm/ReportHistoryStore.d.ts +8 -0
  36. package/dist/esm/ReportHistoryStore.js +199 -0
  37. package/dist/esm/SafeString.js +2 -2
  38. package/dist/esm/Templates.d.ts +58 -0
  39. package/dist/esm/Templates.js +196 -0
  40. package/dist/esm/Url.d.ts +10 -0
  41. package/dist/esm/Url.js +15 -0
  42. package/dist/esm/components/CopyText.d.ts +45 -0
  43. package/dist/esm/components/CopyText.js +56 -0
  44. package/dist/esm/components/StepProgressBar.d.ts +26 -0
  45. package/dist/esm/components/StepProgressBar.js +40 -0
  46. package/dist/esm/components/form/element/combobox.d.ts +231 -0
  47. package/dist/esm/components/form/element/combobox.js +812 -0
  48. package/dist/esm/components/form/element/dropdown.d.ts +35 -0
  49. package/dist/esm/components/form/element/dropdown.js +61 -0
  50. package/dist/esm/components/form/element/dropdownItem.d.ts +55 -0
  51. package/dist/esm/components/form/element/dropdownItem.js +113 -0
  52. package/dist/esm/components/form/element/onOffSwitch.d.ts +94 -0
  53. package/dist/esm/components/form/element/onOffSwitch.js +167 -0
  54. package/dist/esm/components/form/element/switch.d.ts +58 -0
  55. package/dist/esm/components/form/element/switch.js +98 -0
  56. package/dist/esm/fastMerge.d.ts +9 -0
  57. package/dist/esm/fastMerge.js +58 -0
  58. package/dist/esm/index.d.ts +22 -0
  59. package/dist/esm/index.js +22 -0
  60. package/dist/esm/jquery.expensifyIframify.d.ts +9 -0
  61. package/dist/esm/jquery.expensifyIframify.js +397 -0
  62. package/dist/esm/md5.d.ts +2 -0
  63. package/dist/esm/md5.js +170 -0
  64. package/dist/esm/mixins/PubSub.d.ts +20 -0
  65. package/dist/esm/mixins/PubSub.js +47 -0
  66. package/dist/esm/mixins/extraClasses.d.ts +8 -0
  67. package/dist/esm/mixins/extraClasses.js +37 -0
  68. package/dist/esm/mixins/validationClasses.d.ts +12 -0
  69. package/dist/esm/mixins/validationClasses.js +30 -0
  70. package/dist/esm/str.d.ts +604 -0
  71. package/dist/esm/str.js +1036 -0
  72. package/dist/esm/tlds.d.ts +2 -0
  73. package/dist/esm/tlds.js +2 -0
  74. package/dist/esm/utils.d.ts +30 -0
  75. package/dist/esm/utils.js +65 -0
  76. package/dist/index.d.ts +1 -0
  77. package/dist/index.js +8 -1
  78. package/package.json +221 -4
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @param {jquery.Deferred} promise
3
+ * @param {String} [extractedProperty]
4
+ *
5
+ * @returns {Object}
6
+ */
7
+ export default function APIDeferred(promise: jquery.Deferred, extractedProperty?: string): Object;
@@ -0,0 +1,216 @@
1
+ /**
2
+ * ----------------------------------------------------------------------------------------------
3
+ * WIP, This is in the process of migration from web-e. Please add methods to this as is needed.|
4
+ * ----------------------------------------------------------------------------------------------
5
+ */
6
+ import get from 'lodash/get';
7
+ import once from 'lodash/once';
8
+ import * as Utils from './utils';
9
+ import * as Func from './Func';
10
+ /**
11
+ * @param {jquery.Deferred} promise
12
+ * @param {String} [extractedProperty]
13
+ *
14
+ * @returns {Object}
15
+ */
16
+ export default function APIDeferred(promise, extractedProperty) {
17
+ /**
18
+ * @private
19
+ */
20
+ const extractedPropertyName = extractedProperty || null;
21
+ let cachedResponse = null;
22
+ const doneCallbacks = [];
23
+ const alwaysCallbacks = [];
24
+ const unhandledCallbacks = [];
25
+ const failCallbacks = [];
26
+ const errorHandlers = {};
27
+ if (!promise) {
28
+ throw new Error('Cannot instantiate APIDeferred without a Deferred promise');
29
+ }
30
+ /**
31
+ * @private
32
+ * @param {Object} [response]
33
+ * @returns {?Number}
34
+ */
35
+ function extractJSONCode(response) {
36
+ return response ? response.jsonCode : null;
37
+ }
38
+ /**
39
+ * Called when the jsonCode is not 200 and invokes the appropriate callbacks for the jsonCode
40
+ * If no callback is defined for the jsonCode then the unhandledCallbacks are invoked
41
+ * The failCallbacks are always called
42
+ *
43
+ * @private
44
+ * @param {Number} jsonCode
45
+ * @param {Object} [response]
46
+ */
47
+ function handleError(jsonCode, response) {
48
+ // Look for handlers for this error code
49
+ const handlers = get(errorHandlers, jsonCode, []);
50
+ if (handlers.length > 0) {
51
+ Func.bulkInvoke(handlers, [jsonCode, response]);
52
+ }
53
+ else {
54
+ // No explicit handlers, call the unhandled callbacks
55
+ Func.bulkInvoke(unhandledCallbacks, [jsonCode, response]);
56
+ }
57
+ // Always run the "fail" callbacks in case of error
58
+ Func.bulkInvoke(failCallbacks, [jsonCode, response]);
59
+ }
60
+ /**
61
+ * Called when network call succeeds or when a callback is added via any of the following methods after the promise is resolved:
62
+ * done(), always(), handle(), unhandled(), or fail()
63
+ *
64
+ * @private
65
+ * @param {Object} [response]
66
+ */
67
+ function handleDone(response) {
68
+ let returnedData;
69
+ // Figure out if we need to extract a property from the response, and if it is there.
70
+ const jsonCode = extractJSONCode(response);
71
+ const propertyRequested = extractedPropertyName && extractedPropertyName !== null;
72
+ const requestedPropertyPresent = propertyRequested && response && response[extractedPropertyName] !== undefined;
73
+ const propertyRequestedButMissing = propertyRequested && !requestedPropertyPresent;
74
+ // Save the response for any callbacks that might run in the future
75
+ cachedResponse = response;
76
+ // Handle three different success/failure scenarios: ok (jsonCode == 200), exception (jsonCode != 200), other error
77
+ if (jsonCode === 200 && (!propertyRequested || requestedPropertyPresent)) {
78
+ // Get the data that was requested
79
+ returnedData = propertyRequested && requestedPropertyPresent ? response[extractedPropertyName] : response;
80
+ // And then run the success callbacks
81
+ Func.bulkInvoke(doneCallbacks, [returnedData]);
82
+ }
83
+ else if (jsonCode !== null && jsonCode !== 200) {
84
+ // Exception thrown, handle it
85
+ handleError(jsonCode, response);
86
+ }
87
+ else {
88
+ // Edge cases:
89
+ // If a specific property was requested but is missing, or if we got a blank response, throw an error
90
+ if (propertyRequestedButMissing) {
91
+ throw new Error(`Requested property " ${extractedPropertyName}" missing from response`);
92
+ }
93
+ if (!response) {
94
+ throw new Error('Blank response returned from API');
95
+ }
96
+ }
97
+ // Always run the "always" callbacks
98
+ Func.bulkInvoke(alwaysCallbacks, [response]);
99
+ }
100
+ /**
101
+ * Re-runs the "done" flow with a saved response to ensure that all callbacks are invoked,
102
+ * even if they were added after the deferred was resolved
103
+ *
104
+ * @private
105
+ */
106
+ function ensureFutureCallbacksFire() {
107
+ if (promise.state() === 'pending') {
108
+ return;
109
+ }
110
+ // Re-run the done handler with the response we saved
111
+ handleDone(cachedResponse);
112
+ }
113
+ // Attach the function to be called when the promise is resolved
114
+ // See handleDone() for more details
115
+ promise.done(handleDone);
116
+ return {
117
+ /**
118
+ * Attaches a callback that will be invoked when the jsonCode is 200
119
+ *
120
+ * @param {Function} callback A function that takes the response as a parameter
121
+ *
122
+ * @returns {APIDeferred} itself, for chaining
123
+ */
124
+ done(callback) {
125
+ if (Utils.isFunction(callback)) {
126
+ doneCallbacks.push(once(callback));
127
+ ensureFutureCallbacksFire();
128
+ }
129
+ return this;
130
+ },
131
+ /**
132
+ * Attaches a callback that will always be invoked
133
+ *
134
+ * @param {Function} callback A function that takes the response as a parameter
135
+ *
136
+ * @returns {APIDeferred} itself, for chaining
137
+ */
138
+ always(callback) {
139
+ if (Utils.isFunction(callback)) {
140
+ alwaysCallbacks.push(once(callback));
141
+ ensureFutureCallbacksFire();
142
+ }
143
+ return this;
144
+ },
145
+ /**
146
+ * Attaches a callback that will be invoked on non-200 jsonCodes
147
+ * Callbacks for jsonCode 200 are expected to be attached with done() and are therefore ignored here
148
+ *
149
+ * @param {Number[]} jsonCodes A list of error codes to handle
150
+ * @param {Function} callback A function that takes the jsonCode and response as parameters
151
+ *
152
+ * @returns {APIDeferred} itself, for chaining
153
+ */
154
+ handle(jsonCodes, callback) {
155
+ if (Utils.isFunction(callback)) {
156
+ for (const code of jsonCodes) {
157
+ if (code === 200) {
158
+ continue;
159
+ }
160
+ if (!errorHandlers[code]) {
161
+ errorHandlers[code] = [];
162
+ }
163
+ errorHandlers[code].push(once(callback));
164
+ }
165
+ ensureFutureCallbacksFire();
166
+ }
167
+ return this;
168
+ },
169
+ /**
170
+ * Attaches a callback that will be invoked on all errors not explicitly handled via handle()
171
+ *
172
+ * @param {Function} callback A function that takes the jsonCode and response as parameters
173
+ *
174
+ * @returns {APIDeferred} itself, for chaining
175
+ */
176
+ unhandled(callback) {
177
+ if (Utils.isFunction(callback)) {
178
+ unhandledCallbacks.push(once(callback));
179
+ ensureFutureCallbacksFire();
180
+ }
181
+ return this;
182
+ },
183
+ /**
184
+ * Attaches a callback that will be always be invoked when the API does NOT return jsonCode 200, regardless of
185
+ * handle() or unhandled()
186
+ *
187
+ * @param {Function} callback A function that takes the jsonCode and response as parameters
188
+ *
189
+ * @returns {APIDeferred} itself, for chaining
190
+ */
191
+ fail(callback) {
192
+ if (Utils.isFunction(callback)) {
193
+ failCallbacks.push(once(callback));
194
+ ensureFutureCallbacksFire();
195
+ }
196
+ return this;
197
+ },
198
+ /**
199
+ * Attaches a callback that will be invoked when this deferred resolves successfully
200
+ *
201
+ * @param {Function} callback A function that takes the response as a parameter
202
+ *
203
+ * @returns {APIDeferred} itself, for chaining
204
+ */
205
+ then(callback) {
206
+ return promise.then((response) => {
207
+ const responseCode = extractJSONCode(response);
208
+ if (responseCode !== 200 || !Utils.isFunction(callback)) {
209
+ return;
210
+ }
211
+ Func.invoke(callback, [response]);
212
+ return this;
213
+ });
214
+ },
215
+ };
216
+ }
@@ -0,0 +1,19 @@
1
+ declare namespace _default {
2
+ export { BROWSERS };
3
+ export { MOBILE_PLATFORMS };
4
+ export let browser: string;
5
+ export let mobileDevice: string;
6
+ }
7
+ export default _default;
8
+ declare namespace BROWSERS {
9
+ let EDGE: string;
10
+ let CHROME: string;
11
+ let SAFARI: string;
12
+ let OPERA: string;
13
+ let EXPLORER: string;
14
+ let MOZILLA: string;
15
+ }
16
+ declare namespace MOBILE_PLATFORMS {
17
+ let iOS: string;
18
+ let android: string;
19
+ }
@@ -0,0 +1,105 @@
1
+ import * as Utils from './utils';
2
+ const BROWSERS = {
3
+ EDGE: 'Edge',
4
+ CHROME: 'Chrome',
5
+ SAFARI: 'Safari',
6
+ OPERA: 'Opera',
7
+ EXPLORER: 'Explorer',
8
+ MOZILLA: 'Mozilla',
9
+ };
10
+ const MOBILE_PLATFORMS = {
11
+ iOS: 'iOS',
12
+ android: 'android',
13
+ };
14
+ function searchString() {
15
+ if (!Utils.isWindowAvailable() || !Utils.isNavigatorAvailable()) {
16
+ return '';
17
+ }
18
+ const data = [
19
+ {
20
+ string: navigator.userAgent,
21
+ subString: 'Edge',
22
+ identity: BROWSERS.EDGE,
23
+ },
24
+ {
25
+ string: navigator.userAgent,
26
+ subString: 'Chrome',
27
+ identity: BROWSERS.CHROME,
28
+ },
29
+ {
30
+ string: navigator.vendor,
31
+ subString: 'Apple',
32
+ identity: BROWSERS.SAFARI,
33
+ },
34
+ {
35
+ prop: window.opera,
36
+ identity: BROWSERS.OPERA,
37
+ },
38
+ {
39
+ string: navigator.userAgent,
40
+ subString: 'Edge',
41
+ identity: BROWSERS.EDGE,
42
+ },
43
+ {
44
+ string: navigator.userAgent,
45
+ subString: 'MSIE',
46
+ identity: BROWSERS.EXPLORER,
47
+ },
48
+ {
49
+ string: navigator.userAgent,
50
+ subString: '.NET',
51
+ identity: BROWSERS.EXPLORER,
52
+ },
53
+ {
54
+ string: navigator.userAgent,
55
+ subString: 'Gecko',
56
+ identity: BROWSERS.MOZILLA,
57
+ },
58
+ ];
59
+ let dataString;
60
+ let dataProp;
61
+ for (let i = 0; i < data.length; i++) {
62
+ dataString = data[i].string;
63
+ dataProp = data[i].prop;
64
+ if (dataString) {
65
+ if (dataString.indexOf(data[i].subString) !== -1) {
66
+ return data[i].identity;
67
+ }
68
+ }
69
+ else if (dataProp) {
70
+ return data[i].identity;
71
+ }
72
+ }
73
+ return '';
74
+ }
75
+ function getMobileDevice() {
76
+ if (!Utils.isNavigatorAvailable() || !navigator.userAgent) {
77
+ return '';
78
+ }
79
+ const data = [
80
+ {
81
+ devices: ['iPhone', 'iPad', 'iPod'],
82
+ identity: MOBILE_PLATFORMS.iOS,
83
+ },
84
+ {
85
+ devices: ['Android'],
86
+ identity: MOBILE_PLATFORMS.android,
87
+ },
88
+ ];
89
+ const dataString = navigator.userAgent;
90
+ for (let i = 0; i < data.length; i++) {
91
+ const { devices, identity } = data[i];
92
+ for (let j = 0; j < devices.length; j++) {
93
+ if (dataString.indexOf(devices[j]) !== -1) {
94
+ return identity;
95
+ }
96
+ }
97
+ }
98
+ return '';
99
+ }
100
+ export default {
101
+ BROWSERS,
102
+ MOBILE_PLATFORMS,
103
+ browser: searchString(),
104
+ mobileDevice: getMobileDevice(),
105
+ };
package/dist/esm/CLI.js CHANGED
@@ -1,3 +1,12 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  /**
2
11
  * This file contains a CLI utility class which can be used to declaratively implement a strongly-typed CLI.
3
12
  * You provide a CLIConfig defining your arguments, then the class will handle parsing argv, type validation, error handling, and help messages.
@@ -6,15 +15,11 @@ import * as readline from 'readline';
6
15
  import SafeString from './SafeString.js';
7
16
  class CLI {
8
17
  constructor(config) {
18
+ var _a, _b, _c, _d, _e, _f;
9
19
  this.config = config;
10
20
  const rawArgs = process.argv.slice(2);
11
21
  // Initialize all flags to false by default (including built-in flags)
12
- this.flags = {
13
- ...Object.fromEntries(Object.keys(config.flags ?? {}).map((key) => [key, false])),
14
- yes: false,
15
- no: false,
16
- help: false,
17
- };
22
+ this.flags = Object.assign(Object.assign({}, Object.fromEntries(Object.keys((_a = config.flags) !== null && _a !== void 0 ? _a : {}).map((key) => [key, false]))), { yes: false, no: false, help: false });
18
23
  try {
19
24
  const parsedNamedArgs = {};
20
25
  const parsedPositionalArgs = {};
@@ -41,7 +46,7 @@ class CLI {
41
46
  argValueBeforeParse = rawArgValue;
42
47
  }
43
48
  else {
44
- argValueBeforeParse = rawArgs.at(++i) ?? '';
49
+ argValueBeforeParse = (_b = rawArgs.at(++i)) !== null && _b !== void 0 ? _b : '';
45
50
  if (!argValueBeforeParse || argValueBeforeParse.startsWith('--')) {
46
51
  throw new Error(`Missing value for --${rawArgName}`);
47
52
  }
@@ -56,7 +61,7 @@ class CLI {
56
61
  }
57
62
  else {
58
63
  // Arg is a positional arg
59
- const spec = config.positionalArgs?.at(positionalIndex);
64
+ const spec = (_c = config.positionalArgs) === null || _c === void 0 ? void 0 : _c.at(positionalIndex);
60
65
  if (spec === undefined) {
61
66
  throw new Error(`Unexpected arg: ${rawArg}`);
62
67
  }
@@ -84,7 +89,7 @@ class CLI {
84
89
  }
85
90
  // Handle supersession logic
86
91
  const supersededArgs = new Set();
87
- for (const [name, spec] of Object.entries(config.namedArgs ?? {})) {
92
+ for (const [name, spec] of Object.entries((_d = config.namedArgs) !== null && _d !== void 0 ? _d : {})) {
88
93
  if (providedNamedArgs.has(name) && spec.supersedes) {
89
94
  for (const supersededArg of spec.supersedes) {
90
95
  supersededArgs.add(supersededArg);
@@ -95,7 +100,7 @@ class CLI {
95
100
  }
96
101
  }
97
102
  // Validate that all required args are present, assign defaults where values are not parsed
98
- for (const [name, spec] of Object.entries(config.namedArgs ?? {})) {
103
+ for (const [name, spec] of Object.entries((_e = config.namedArgs) !== null && _e !== void 0 ? _e : {})) {
99
104
  if (name in parsedNamedArgs) {
100
105
  if (supersededArgs.has(name)) {
101
106
  parsedNamedArgs[name] = undefined;
@@ -117,7 +122,7 @@ class CLI {
117
122
  throw new Error(`Missing required named argument --${name}`);
118
123
  }
119
124
  }
120
- for (const spec of config.positionalArgs ?? []) {
125
+ for (const spec of (_f = config.positionalArgs) !== null && _f !== void 0 ? _f : []) {
121
126
  if (!(spec.name in parsedPositionalArgs)) {
122
127
  if (spec.default !== undefined) {
123
128
  parsedPositionalArgs[spec.name] = spec.default;
@@ -149,8 +154,9 @@ class CLI {
149
154
  }
150
155
  }
151
156
  printHelp() {
157
+ var _a;
152
158
  const { flags = {}, namedArgs = {}, positionalArgs = [] } = this.config;
153
- const scriptName = process.argv.at(1) ?? 'script.ts';
159
+ const scriptName = (_a = process.argv.at(1)) !== null && _a !== void 0 ? _a : 'script.ts';
154
160
  const positionalUsage = positionalArgs
155
161
  .map((arg) => {
156
162
  const label = arg.variadic ? `${arg.name}...` : arg.name;
@@ -212,23 +218,25 @@ class CLI {
212
218
  * If --yes flag was passed, returns true immediately without prompting.
213
219
  * If --no flag was passed, returns false immediately without prompting.
214
220
  */
215
- async promptUserConfirmation(message) {
216
- // Check for built-in flags first
217
- if (this.flags.yes) {
218
- return true;
219
- }
220
- if (this.flags.no) {
221
- return false;
222
- }
223
- const rl = readline.createInterface({
224
- input: process.stdin,
225
- output: process.stdout,
226
- });
227
- return new Promise((resolve) => {
228
- rl.question(message, (answer) => {
229
- rl.close();
230
- const normalizedAnswer = answer.trim().toLowerCase();
231
- resolve(normalizedAnswer === 'y' || normalizedAnswer === 'yes');
221
+ promptUserConfirmation(message) {
222
+ return __awaiter(this, void 0, void 0, function* () {
223
+ // Check for built-in flags first
224
+ if (this.flags.yes) {
225
+ return true;
226
+ }
227
+ if (this.flags.no) {
228
+ return false;
229
+ }
230
+ const rl = readline.createInterface({
231
+ input: process.stdin,
232
+ output: process.stdout,
233
+ });
234
+ return new Promise((resolve) => {
235
+ rl.question(message, (answer) => {
236
+ rl.close();
237
+ const normalizedAnswer = answer.trim().toLowerCase();
238
+ resolve(normalizedAnswer === 'y' || normalizedAnswer === 'yes');
239
+ });
232
240
  });
233
241
  });
234
242
  }