expensify-common 2.0.187 → 2.0.189

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 (83) hide show
  1. package/dist/CLI.d.ts +160 -0
  2. package/dist/CLI.js +282 -0
  3. package/dist/esm/API.d.ts +11 -0
  4. package/dist/esm/API.js +786 -0
  5. package/dist/esm/APIDeferred.d.ts +7 -0
  6. package/dist/esm/APIDeferred.js +216 -0
  7. package/dist/esm/BrowserDetect.d.ts +19 -0
  8. package/dist/esm/BrowserDetect.js +105 -0
  9. package/dist/esm/CLI.d.ts +160 -0
  10. package/dist/esm/CLI.js +244 -0
  11. package/dist/esm/CONST.d.ts +1727 -0
  12. package/dist/esm/CONST.js +1847 -0
  13. package/dist/esm/Cookie.d.ts +68 -0
  14. package/dist/esm/Cookie.js +159 -0
  15. package/dist/esm/CredentialsWrapper.d.ts +32 -0
  16. package/dist/esm/CredentialsWrapper.js +46 -0
  17. package/dist/esm/Device.d.ts +8 -0
  18. package/dist/esm/Device.js +24 -0
  19. package/dist/esm/ExpenseRule.d.ts +39 -0
  20. package/dist/esm/ExpenseRule.js +77 -0
  21. package/dist/esm/ExpensiMark.d.ts +197 -0
  22. package/dist/esm/ExpensiMark.js +1374 -0
  23. package/dist/esm/Func.d.ts +40 -0
  24. package/dist/esm/Func.js +69 -0
  25. package/dist/esm/Log.d.ts +3 -0
  26. package/dist/esm/Log.js +35 -0
  27. package/dist/esm/Logger.d.ts +82 -0
  28. package/dist/esm/Logger.js +138 -0
  29. package/dist/esm/Network.d.ts +6 -0
  30. package/dist/esm/Network.js +168 -0
  31. package/dist/esm/Num.d.ts +95 -0
  32. package/dist/esm/Num.js +190 -0
  33. package/dist/esm/PageEvent.d.ts +25 -0
  34. package/dist/esm/PageEvent.js +22 -0
  35. package/dist/esm/PubSub.d.ts +2 -0
  36. package/dist/esm/PubSub.js +111 -0
  37. package/dist/esm/ReportHistoryStore.d.ts +8 -0
  38. package/dist/esm/ReportHistoryStore.js +199 -0
  39. package/dist/esm/SafeString.d.ts +8 -0
  40. package/{lib/SafeString.ts → dist/esm/SafeString.js} +8 -13
  41. package/dist/esm/Templates.d.ts +58 -0
  42. package/dist/esm/Templates.js +196 -0
  43. package/dist/esm/Url.d.ts +10 -0
  44. package/dist/esm/Url.js +15 -0
  45. package/dist/esm/components/CopyText.d.ts +45 -0
  46. package/dist/esm/components/CopyText.js +56 -0
  47. package/dist/esm/components/StepProgressBar.d.ts +26 -0
  48. package/dist/esm/components/StepProgressBar.js +40 -0
  49. package/dist/esm/components/form/element/combobox.d.ts +231 -0
  50. package/dist/esm/components/form/element/combobox.js +812 -0
  51. package/dist/esm/components/form/element/dropdown.d.ts +35 -0
  52. package/dist/esm/components/form/element/dropdown.js +61 -0
  53. package/dist/esm/components/form/element/dropdownItem.d.ts +55 -0
  54. package/dist/esm/components/form/element/dropdownItem.js +113 -0
  55. package/dist/esm/components/form/element/onOffSwitch.d.ts +94 -0
  56. package/dist/esm/components/form/element/onOffSwitch.js +167 -0
  57. package/dist/esm/components/form/element/switch.d.ts +58 -0
  58. package/dist/esm/components/form/element/switch.js +98 -0
  59. package/dist/esm/fastMerge.d.ts +9 -0
  60. package/dist/esm/fastMerge.js +58 -0
  61. package/dist/esm/index.d.ts +22 -0
  62. package/dist/esm/index.js +22 -0
  63. package/dist/esm/jquery.expensifyIframify.d.ts +9 -0
  64. package/dist/esm/jquery.expensifyIframify.js +397 -0
  65. package/dist/esm/md5.d.ts +2 -0
  66. package/dist/esm/md5.js +170 -0
  67. package/dist/esm/mixins/PubSub.d.ts +20 -0
  68. package/dist/esm/mixins/PubSub.js +47 -0
  69. package/dist/esm/mixins/extraClasses.d.ts +8 -0
  70. package/dist/esm/mixins/extraClasses.js +37 -0
  71. package/dist/esm/mixins/validationClasses.d.ts +12 -0
  72. package/dist/esm/mixins/validationClasses.js +30 -0
  73. package/dist/esm/package.json +3 -0
  74. package/dist/esm/str.d.ts +604 -0
  75. package/dist/esm/str.js +1036 -0
  76. package/dist/esm/tlds.d.ts +2 -0
  77. package/dist/esm/tlds.js +2 -0
  78. package/dist/esm/utils.d.ts +30 -0
  79. package/dist/esm/utils.js +65 -0
  80. package/dist/index.d.ts +1 -0
  81. package/dist/index.js +8 -1
  82. package/package.json +228 -8
  83. package/lib/CLI.ts +0 -409
@@ -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
+ };
@@ -0,0 +1,160 @@
1
+ import type { NonEmptyObject, NonEmptyTuple } from 'type-fest';
2
+ /**
3
+ * A base CLI arg has only a description, which we will use in the help/usage message (built-in to any CLI).
4
+ */
5
+ type CLIArg = {
6
+ description: string;
7
+ };
8
+ /**
9
+ * A boolean arg is characterized only by its presence or absence so has no other fields,
10
+ * but we'll create a type alias to clearly distinguish it from other argument types.
11
+ */
12
+ type BooleanArg = CLIArg;
13
+ /**
14
+ * Any other argument is provided raw in process.argv as a string.
15
+ * It can remain a string, or can be transformed into another type by a custom `parse` function.
16
+ * It can be optional (by providing a default) or required (no default value).
17
+ * It can also supersede other named arguments when provided.
18
+ */
19
+ type StringArg<T = unknown> = CLIArg & {
20
+ default?: T;
21
+ parse?: (val: string) => T;
22
+ supersedes?: string[];
23
+ required?: boolean;
24
+ };
25
+ /**
26
+ * A positional argument is just a string arg, but also must be assigned a name which we will eventually expose the CLI consumer.
27
+ * If `variadic` is true, this must be the last positional arg and it collects all remaining positional args into a string[].
28
+ */
29
+ type PositionalArg<T = unknown> = StringArg<T> & {
30
+ name: string;
31
+ variadic?: true;
32
+ };
33
+ /**
34
+ * This type represents the config for a CLI.
35
+ * The last positional arg can be marked `variadic: true` to collect all remaining positional args into a string[].
36
+ */
37
+ type CLIConfig = NonEmptyObject<{
38
+ /**
39
+ * Record of named flags that are fully characterized by their presence or absence (present=true,absent=false).
40
+ * @example `--verbose`
41
+ */
42
+ flags?: Record<string, BooleanArg>;
43
+ /**
44
+ * Record of named arguments that are represented by a key and a value.
45
+ * @example `--threads=8`
46
+ * @example `--name Rory`
47
+ */
48
+ namedArgs?: Record<string, StringArg>;
49
+ /**
50
+ * Tuple of positional args.
51
+ * @example `myScript.ts arg1 arg2 arg3`
52
+ */
53
+ positionalArgs?: NonEmptyTuple<PositionalArg>;
54
+ }>;
55
+ /**
56
+ * Record of flags to boolean after parsing.
57
+ */
58
+ type ParsedFlags<Flags extends CLIConfig['flags']> = {
59
+ [K in keyof NonNullable<Flags>]: boolean;
60
+ };
61
+ /**
62
+ * Utility type to infer the final value of a string param. Either:
63
+ * - it's a plain string, or
64
+ * - it has a parse function and the final value is inferred from the return type of that function
65
+ */
66
+ type InferStringArgParsedValue<T extends StringArg> = T extends {
67
+ parse: (val: string) => infer R;
68
+ } ? R : string;
69
+ /**
70
+ * Record of named args after parsing.
71
+ */
72
+ type ParsedNamedArgs<NamedArgs extends CLIConfig['namedArgs']> = {
73
+ [K in keyof NonNullable<NamedArgs>]: InferStringArgParsedValue<NonNullable<NamedArgs>[K]>;
74
+ };
75
+ /**
76
+ * Record of positional args after parsing.
77
+ * Variadic args are parsed as string[]; all others use InferStringArgParsedValue.
78
+ */
79
+ type ParsedPositionalArgs<PositionalArgs extends CLIConfig['positionalArgs']> = {
80
+ [K in NonNullable<PositionalArgs>[number] as K['name']]: K extends {
81
+ variadic: true;
82
+ } ? string[] : InferStringArgParsedValue<K>;
83
+ };
84
+ /**
85
+ * Utility to parse command-line arguments to a script.
86
+ *
87
+ * @example
88
+ * ```
89
+ * const cli = new CLI({
90
+ * flags: {
91
+ * verbose: {
92
+ * description: 'Enable verbose logging',
93
+ * },
94
+ * },
95
+ * namedArgs: {
96
+ * time: {
97
+ * description: 'Time of day to greet (morning or evening)',
98
+ * default: 'morning',
99
+ * parse: (val) => {
100
+ * if (val !== 'morning' && val !== 'evening') {
101
+ * throw new Error('Must be "morning" or "evening"');
102
+ * }
103
+ * return val as 'morning' | 'evening';
104
+ * },
105
+ * },
106
+ * },
107
+ * positionalArgs: [
108
+ * {
109
+ * name: 'firstName'
110
+ * description: 'First name to greet',
111
+ * },
112
+ * {
113
+ * name: 'lastName',
114
+ * description: 'Last name to greet',
115
+ * default: '',
116
+ * },
117
+ * ],
118
+ * });
119
+ *
120
+ * let fullName = cli.positionalArgs.firstName;
121
+ * if (cli.flags.verbose) {
122
+ * fullName += cli.positionalArgs.lastName;
123
+ * }
124
+ * console.log(fullName);
125
+ * console.log(cli.namedArgs.time);
126
+ * ```
127
+ */
128
+ /**
129
+ * Built-in flags that are always available on any CLI.
130
+ */
131
+ type BuiltInFlags = {
132
+ yes: boolean;
133
+ no: boolean;
134
+ help: boolean;
135
+ };
136
+ declare class CLI<TConfig extends CLIConfig> {
137
+ private readonly config;
138
+ /**
139
+ * Flags after parsing (includes built-in flags like --yes, --no, and --help).
140
+ */
141
+ readonly flags: ParsedFlags<TConfig['flags']> & BuiltInFlags;
142
+ /**
143
+ * Named args after parsing.
144
+ */
145
+ readonly namedArgs: ParsedNamedArgs<TConfig['namedArgs']>;
146
+ /**
147
+ * Positional args after parsing, collected into a record keyed by the name of each arg.
148
+ */
149
+ readonly positionalArgs: ParsedPositionalArgs<TConfig['positionalArgs']>;
150
+ constructor(config: TConfig);
151
+ private printHelp;
152
+ private static parseStringArg;
153
+ /**
154
+ * Prompts the user for confirmation and returns true if they confirm (y/yes), false otherwise.
155
+ * If --yes flag was passed, returns true immediately without prompting.
156
+ * If --no flag was passed, returns false immediately without prompting.
157
+ */
158
+ promptUserConfirmation(message: string): Promise<boolean>;
159
+ }
160
+ export default CLI;