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.
- package/dist/Logger.js +11 -1
- package/dist/esm/API.d.ts +11 -0
- package/dist/esm/API.js +786 -0
- package/dist/esm/APIDeferred.d.ts +7 -0
- package/dist/esm/APIDeferred.js +216 -0
- package/dist/esm/BrowserDetect.d.ts +19 -0
- package/dist/esm/BrowserDetect.js +105 -0
- package/dist/esm/CLI.js +37 -29
- package/dist/esm/CONST.d.ts +1727 -0
- package/dist/esm/CONST.js +1847 -0
- package/dist/esm/Cookie.d.ts +68 -0
- package/dist/esm/Cookie.js +159 -0
- package/dist/esm/CredentialsWrapper.d.ts +32 -0
- package/dist/esm/CredentialsWrapper.js +46 -0
- package/dist/esm/Device.d.ts +8 -0
- package/dist/esm/Device.js +24 -0
- package/dist/esm/ExpenseRule.d.ts +39 -0
- package/dist/esm/ExpenseRule.js +77 -0
- package/dist/esm/ExpensiMark.d.ts +197 -0
- package/dist/esm/ExpensiMark.js +1374 -0
- package/dist/esm/Func.d.ts +40 -0
- package/dist/esm/Func.js +69 -0
- package/dist/esm/Log.d.ts +3 -0
- package/dist/esm/Log.js +35 -0
- package/dist/esm/Logger.d.ts +82 -0
- package/dist/esm/Logger.js +148 -0
- package/dist/esm/Network.d.ts +6 -0
- package/dist/esm/Network.js +168 -0
- package/dist/esm/Num.d.ts +95 -0
- package/dist/esm/Num.js +190 -0
- package/dist/esm/PageEvent.d.ts +25 -0
- package/dist/esm/PageEvent.js +22 -0
- package/dist/esm/PubSub.d.ts +2 -0
- package/dist/esm/PubSub.js +111 -0
- package/dist/esm/ReportHistoryStore.d.ts +8 -0
- package/dist/esm/ReportHistoryStore.js +199 -0
- package/dist/esm/SafeString.js +2 -2
- package/dist/esm/Templates.d.ts +58 -0
- package/dist/esm/Templates.js +196 -0
- package/dist/esm/Url.d.ts +10 -0
- package/dist/esm/Url.js +15 -0
- package/dist/esm/components/CopyText.d.ts +45 -0
- package/dist/esm/components/CopyText.js +56 -0
- package/dist/esm/components/StepProgressBar.d.ts +26 -0
- package/dist/esm/components/StepProgressBar.js +40 -0
- package/dist/esm/components/form/element/combobox.d.ts +231 -0
- package/dist/esm/components/form/element/combobox.js +812 -0
- package/dist/esm/components/form/element/dropdown.d.ts +35 -0
- package/dist/esm/components/form/element/dropdown.js +61 -0
- package/dist/esm/components/form/element/dropdownItem.d.ts +55 -0
- package/dist/esm/components/form/element/dropdownItem.js +113 -0
- package/dist/esm/components/form/element/onOffSwitch.d.ts +94 -0
- package/dist/esm/components/form/element/onOffSwitch.js +167 -0
- package/dist/esm/components/form/element/switch.d.ts +58 -0
- package/dist/esm/components/form/element/switch.js +98 -0
- package/dist/esm/fastMerge.d.ts +9 -0
- package/dist/esm/fastMerge.js +58 -0
- package/dist/esm/index.d.ts +22 -0
- package/dist/esm/index.js +22 -0
- package/dist/esm/jquery.expensifyIframify.d.ts +9 -0
- package/dist/esm/jquery.expensifyIframify.js +397 -0
- package/dist/esm/md5.d.ts +2 -0
- package/dist/esm/md5.js +170 -0
- package/dist/esm/mixins/PubSub.d.ts +20 -0
- package/dist/esm/mixins/PubSub.js +47 -0
- package/dist/esm/mixins/extraClasses.d.ts +8 -0
- package/dist/esm/mixins/extraClasses.js +37 -0
- package/dist/esm/mixins/validationClasses.d.ts +12 -0
- package/dist/esm/mixins/validationClasses.js +30 -0
- package/dist/esm/str.d.ts +604 -0
- package/dist/esm/str.js +1036 -0
- package/dist/esm/tlds.d.ts +2 -0
- package/dist/esm/tlds.js +2 -0
- package/dist/esm/utils.d.ts +30 -0
- package/dist/esm/utils.js +65 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +8 -1
- package/package.json +221 -4
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invokes the given callback with the given arguments
|
|
3
|
+
*
|
|
4
|
+
* @param {Function} callback
|
|
5
|
+
* @param {Array} [args]
|
|
6
|
+
* @param {Object} [scope]
|
|
7
|
+
*
|
|
8
|
+
* @returns {Mixed}
|
|
9
|
+
*/
|
|
10
|
+
export function invoke(callback: Function, args?: any[], scope?: Object): Mixed;
|
|
11
|
+
/**
|
|
12
|
+
* This is nearly the same as invoke, except that it assumes that the callback returns a promise. The callback doesn't
|
|
13
|
+
* HAVE to return a promise, but it CAN, and if it doesn't, then we provide a promise
|
|
14
|
+
*
|
|
15
|
+
* @param {Function} callback
|
|
16
|
+
* @param {Array} [args]
|
|
17
|
+
* @param {Object} [scope]
|
|
18
|
+
*
|
|
19
|
+
* @returns {Promise}
|
|
20
|
+
*/
|
|
21
|
+
export function invokeAsync(callback: Function, args?: any[], scope?: Object): Promise<any>;
|
|
22
|
+
/**
|
|
23
|
+
* Invokes all the given callbacks with the given arguments
|
|
24
|
+
*
|
|
25
|
+
* @param {Function[]} callbacks
|
|
26
|
+
* @param {Array} [args]
|
|
27
|
+
*/
|
|
28
|
+
export function bulkInvoke(callbacks: Function[], args?: any[]): void;
|
|
29
|
+
/**
|
|
30
|
+
* Throws an uncaught error in an attempt to stop JS execution
|
|
31
|
+
*/
|
|
32
|
+
export function die(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Call the method on a list of objects
|
|
35
|
+
*
|
|
36
|
+
* @param {object|array} list
|
|
37
|
+
* @param {string} methodName
|
|
38
|
+
* @returns {Array}
|
|
39
|
+
*/
|
|
40
|
+
export function mapByName(list: object | array, methodName: string): any[];
|
package/dist/esm/Func.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as Utils from './utils';
|
|
2
|
+
/**
|
|
3
|
+
* Invokes the given callback with the given arguments
|
|
4
|
+
*
|
|
5
|
+
* @param {Function} callback
|
|
6
|
+
* @param {Array} [args]
|
|
7
|
+
* @param {Object} [scope]
|
|
8
|
+
*
|
|
9
|
+
* @returns {Mixed}
|
|
10
|
+
*/
|
|
11
|
+
function invoke(callback, args, scope) {
|
|
12
|
+
if (!Utils.isFunction(callback)) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return callback.apply(scope, args || []);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* This is nearly the same as invoke, except that it assumes that the callback returns a promise. The callback doesn't
|
|
19
|
+
* HAVE to return a promise, but it CAN, and if it doesn't, then we provide a promise
|
|
20
|
+
*
|
|
21
|
+
* @param {Function} callback
|
|
22
|
+
* @param {Array} [args]
|
|
23
|
+
* @param {Object} [scope]
|
|
24
|
+
*
|
|
25
|
+
* @returns {Promise}
|
|
26
|
+
*/
|
|
27
|
+
function invokeAsync(callback, args, scope) {
|
|
28
|
+
if (!Utils.isFunction(callback)) {
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
}
|
|
31
|
+
let promiseFromCallback = callback.apply(scope, args || []);
|
|
32
|
+
// If there was not a promise returned from the prefetch callback, then create a dummy promise and resolve it
|
|
33
|
+
if (!promiseFromCallback) {
|
|
34
|
+
promiseFromCallback = Promise.resolve();
|
|
35
|
+
}
|
|
36
|
+
return promiseFromCallback;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Invokes all the given callbacks with the given arguments
|
|
40
|
+
*
|
|
41
|
+
* @param {Function[]} callbacks
|
|
42
|
+
* @param {Array} [args]
|
|
43
|
+
*/
|
|
44
|
+
function bulkInvoke(callbacks, args) {
|
|
45
|
+
for (const callback of callbacks) {
|
|
46
|
+
invoke(callback, args);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Throws an uncaught error in an attempt to stop JS execution
|
|
51
|
+
*/
|
|
52
|
+
function die() {
|
|
53
|
+
throw new Error('Aborting JavaScript execution');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Call the method on a list of objects
|
|
57
|
+
*
|
|
58
|
+
* @param {object|array} list
|
|
59
|
+
* @param {string} methodName
|
|
60
|
+
* @returns {Array}
|
|
61
|
+
*/
|
|
62
|
+
function mapByName(list, methodName) {
|
|
63
|
+
let arr = list;
|
|
64
|
+
if (!Array.isArray(arr)) {
|
|
65
|
+
arr = Object.values(arr);
|
|
66
|
+
}
|
|
67
|
+
return arr.map((item) => item[methodName].call(item));
|
|
68
|
+
}
|
|
69
|
+
export { invoke, invokeAsync, bulkInvoke, die, mapByName };
|
package/dist/esm/Log.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import API from './API';
|
|
3
|
+
import Network from './Network';
|
|
4
|
+
import Logger from './Logger';
|
|
5
|
+
import * as Utils from './utils';
|
|
6
|
+
/**
|
|
7
|
+
* Network interface for logger.
|
|
8
|
+
*
|
|
9
|
+
* @param {Logger} logger
|
|
10
|
+
* @param {Object} params
|
|
11
|
+
* @param {Object} params.parameters
|
|
12
|
+
* @param {String} params.message
|
|
13
|
+
* @returns {Promise}
|
|
14
|
+
*/
|
|
15
|
+
function serverLoggingCallback(logger, params) {
|
|
16
|
+
return API(Network('/api/')).logToServer(params);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Local log messages for client logging.
|
|
20
|
+
*
|
|
21
|
+
* @param {String} message
|
|
22
|
+
*/
|
|
23
|
+
function clientLoggingCallback(message) {
|
|
24
|
+
if (Utils.isWindowAvailable() && typeof window.g_printableReport !== 'undefined' && window.g_printableReport === true) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (window.console && Utils.isFunction(console.log)) {
|
|
28
|
+
console.log(message);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export default new Logger({
|
|
32
|
+
serverLoggingCallback,
|
|
33
|
+
clientLoggingCallback,
|
|
34
|
+
isDebug: Utils.isWindowAvailable() ? window.DEBUG : false,
|
|
35
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
type Parameters = string | Record<string, unknown> | Array<Record<string, unknown>> | Error;
|
|
2
|
+
type ServerLoggingCallbackOptions = {
|
|
3
|
+
api_setCookie: boolean;
|
|
4
|
+
logPacket: string;
|
|
5
|
+
};
|
|
6
|
+
type ServerLoggingCallback = (logger: Logger, options: ServerLoggingCallbackOptions) => Promise<{
|
|
7
|
+
requestID: string;
|
|
8
|
+
}> | undefined;
|
|
9
|
+
type ClientLoggingCallBack = (message: string, extraData: Parameters) => void;
|
|
10
|
+
type LogLine = {
|
|
11
|
+
message: string;
|
|
12
|
+
parameters: Parameters;
|
|
13
|
+
onlyFlushWithOthers?: boolean;
|
|
14
|
+
timestamp: Date;
|
|
15
|
+
email?: string | null;
|
|
16
|
+
};
|
|
17
|
+
type LoggerOptions = {
|
|
18
|
+
serverLoggingCallback: ServerLoggingCallback;
|
|
19
|
+
isDebug: boolean;
|
|
20
|
+
clientLoggingCallback: ClientLoggingCallBack;
|
|
21
|
+
maxLogLinesBeforeFlush?: number;
|
|
22
|
+
getContextEmail?: () => string | null;
|
|
23
|
+
};
|
|
24
|
+
export default class Logger {
|
|
25
|
+
logLines: LogLine[];
|
|
26
|
+
serverLoggingCallback: ServerLoggingCallback;
|
|
27
|
+
clientLoggingCallback: ClientLoggingCallBack;
|
|
28
|
+
isDebug: boolean;
|
|
29
|
+
maxLogLinesBeforeFlush: number;
|
|
30
|
+
getContextEmail?: () => string | null;
|
|
31
|
+
constructor({ serverLoggingCallback, isDebug, clientLoggingCallback, maxLogLinesBeforeFlush, getContextEmail }: LoggerOptions);
|
|
32
|
+
/**
|
|
33
|
+
* Ask the server to write the log message
|
|
34
|
+
*/
|
|
35
|
+
logToServer(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Add a message to the list
|
|
38
|
+
* @param parameters The parameters associated with the message
|
|
39
|
+
* @param forceFlushToServer Should we force flushing all logs to server?
|
|
40
|
+
* @param onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
|
|
41
|
+
*/
|
|
42
|
+
add(message: string, parameters: Parameters, forceFlushToServer: boolean, onlyFlushWithOthers?: boolean, extraData?: Parameters): void;
|
|
43
|
+
/**
|
|
44
|
+
* Caches an informational message locally, to be sent to the server if
|
|
45
|
+
* needed later.
|
|
46
|
+
*
|
|
47
|
+
* @param message The message to log.
|
|
48
|
+
* @param sendNow if true, the message will be sent right away.
|
|
49
|
+
* @param parameters The parameters to send along with the message
|
|
50
|
+
* @param onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
|
|
51
|
+
*/
|
|
52
|
+
info(message: string, sendNow?: boolean, parameters?: Parameters, onlyFlushWithOthers?: boolean, extraData?: Parameters): void;
|
|
53
|
+
/**
|
|
54
|
+
* Logs an alert.
|
|
55
|
+
*
|
|
56
|
+
* @param message The message to alert.
|
|
57
|
+
* @param parameters The parameters to send along with the message
|
|
58
|
+
* @param includeStackTrace Must be disabled for testing
|
|
59
|
+
*/
|
|
60
|
+
alert(message: string, parameters?: Parameters, includeStackTrace?: boolean): void;
|
|
61
|
+
/**
|
|
62
|
+
* Logs a warn.
|
|
63
|
+
*
|
|
64
|
+
* @param message The message to warn.
|
|
65
|
+
* @param parameters The parameters to send along with the message
|
|
66
|
+
*/
|
|
67
|
+
warn(message: string, parameters?: Parameters): void;
|
|
68
|
+
/**
|
|
69
|
+
* Logs a hmmm.
|
|
70
|
+
*
|
|
71
|
+
* @param message The message to hmmm.
|
|
72
|
+
* @param parameters The parameters to send along with the message
|
|
73
|
+
*/
|
|
74
|
+
hmmm(message: string, parameters?: Parameters): void;
|
|
75
|
+
/**
|
|
76
|
+
* Logs a message in the browser console.
|
|
77
|
+
*
|
|
78
|
+
* @param message The message to log.
|
|
79
|
+
*/
|
|
80
|
+
client(message: string, extraData?: Parameters): void;
|
|
81
|
+
}
|
|
82
|
+
export {};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
const MAX_LOG_LINES_BEFORE_FLUSH = 50;
|
|
2
|
+
// The server drops (and alerts on) any single log message whose byte length exceeds 1MB, so cap
|
|
3
|
+
// each message just below that. We truncate rather than drop so oversized lines are still logged
|
|
4
|
+
// (head of the message + a marker) instead of being lost. The margin leaves room for the marker.
|
|
5
|
+
const ONE_MEGABYTE = 1024 * 1024;
|
|
6
|
+
const MAX_LOG_MESSAGE_LENGTH = ONE_MEGABYTE - 1024;
|
|
7
|
+
export default class Logger {
|
|
8
|
+
constructor({ serverLoggingCallback, isDebug, clientLoggingCallback, maxLogLinesBeforeFlush, getContextEmail }) {
|
|
9
|
+
// An array of log lines that limits itself to a certain number of entries (deleting the oldest)
|
|
10
|
+
this.logLines = [];
|
|
11
|
+
this.serverLoggingCallback = serverLoggingCallback;
|
|
12
|
+
this.clientLoggingCallback = clientLoggingCallback;
|
|
13
|
+
this.isDebug = isDebug;
|
|
14
|
+
this.maxLogLinesBeforeFlush = maxLogLinesBeforeFlush || MAX_LOG_LINES_BEFORE_FLUSH;
|
|
15
|
+
this.getContextEmail = getContextEmail;
|
|
16
|
+
// Public Methods
|
|
17
|
+
this.info = this.info.bind(this);
|
|
18
|
+
this.alert = this.alert.bind(this);
|
|
19
|
+
this.warn = this.warn.bind(this);
|
|
20
|
+
this.hmmm = this.hmmm.bind(this);
|
|
21
|
+
this.client = this.client.bind(this);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Ask the server to write the log message
|
|
25
|
+
*/
|
|
26
|
+
logToServer() {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
// We do not want to call the server with an empty list or if all the lines has onlyFlushWithOthers=true
|
|
29
|
+
if (!this.logLines.length || ((_a = this.logLines) === null || _a === void 0 ? void 0 : _a.every((l) => l.onlyFlushWithOthers))) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// We don't care about log setting web cookies so let's define it as false
|
|
33
|
+
const linesToLog = (_b = this.logLines) === null || _b === void 0 ? void 0 : _b.map((l) => {
|
|
34
|
+
// eslint-disable-next-line no-param-reassign
|
|
35
|
+
delete l.onlyFlushWithOthers;
|
|
36
|
+
return l;
|
|
37
|
+
});
|
|
38
|
+
this.logLines = [];
|
|
39
|
+
const promise = this.serverLoggingCallback(this, {
|
|
40
|
+
api_setCookie: false,
|
|
41
|
+
logPacket: JSON.stringify(linesToLog),
|
|
42
|
+
});
|
|
43
|
+
if (!promise) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
promise.then((response) => {
|
|
47
|
+
if (!response.requestID) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.info('Previous log requestID', false, { requestID: response.requestID }, true);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Add a message to the list
|
|
55
|
+
* @param parameters The parameters associated with the message
|
|
56
|
+
* @param forceFlushToServer Should we force flushing all logs to server?
|
|
57
|
+
* @param onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
|
|
58
|
+
*/
|
|
59
|
+
add(message, parameters, forceFlushToServer, onlyFlushWithOthers = false, extraData = '') {
|
|
60
|
+
// Capture the user's email at the moment this specific log line is created
|
|
61
|
+
// This ensures the log retains user context even if the session is cleared before sending
|
|
62
|
+
let email = null;
|
|
63
|
+
try {
|
|
64
|
+
email = this.getContextEmail ? this.getContextEmail() : null;
|
|
65
|
+
}
|
|
66
|
+
catch (_a) {
|
|
67
|
+
// Silently fail if getContextEmail throws - logging should not crash
|
|
68
|
+
}
|
|
69
|
+
let cappedMessage = message;
|
|
70
|
+
if (message.length > MAX_LOG_MESSAGE_LENGTH) {
|
|
71
|
+
const omittedCount = message.length - MAX_LOG_MESSAGE_LENGTH;
|
|
72
|
+
cappedMessage = `${message.slice(0, MAX_LOG_MESSAGE_LENGTH)}…[truncated ${omittedCount} characters]`;
|
|
73
|
+
}
|
|
74
|
+
const length = this.logLines.push({
|
|
75
|
+
message: cappedMessage,
|
|
76
|
+
parameters,
|
|
77
|
+
onlyFlushWithOthers,
|
|
78
|
+
timestamp: new Date(),
|
|
79
|
+
email,
|
|
80
|
+
});
|
|
81
|
+
if (this.isDebug) {
|
|
82
|
+
this.client(`${message} - ${JSON.stringify(parameters)}`, extraData);
|
|
83
|
+
}
|
|
84
|
+
// If we're over the limit, flush the logs
|
|
85
|
+
if (length > this.maxLogLinesBeforeFlush || forceFlushToServer) {
|
|
86
|
+
this.logToServer();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Caches an informational message locally, to be sent to the server if
|
|
91
|
+
* needed later.
|
|
92
|
+
*
|
|
93
|
+
* @param message The message to log.
|
|
94
|
+
* @param sendNow if true, the message will be sent right away.
|
|
95
|
+
* @param parameters The parameters to send along with the message
|
|
96
|
+
* @param onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
|
|
97
|
+
*/
|
|
98
|
+
info(message, sendNow = false, parameters = '', onlyFlushWithOthers = false, extraData = '') {
|
|
99
|
+
const msg = `[info] ${message}`;
|
|
100
|
+
this.add(msg, parameters, sendNow, onlyFlushWithOthers, extraData);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Logs an alert.
|
|
104
|
+
*
|
|
105
|
+
* @param message The message to alert.
|
|
106
|
+
* @param parameters The parameters to send along with the message
|
|
107
|
+
* @param includeStackTrace Must be disabled for testing
|
|
108
|
+
*/
|
|
109
|
+
alert(message, parameters = {}, includeStackTrace = true) {
|
|
110
|
+
const msg = `[alrt] ${message}`;
|
|
111
|
+
const params = parameters;
|
|
112
|
+
if (includeStackTrace && typeof params === 'object' && !Array.isArray(params)) {
|
|
113
|
+
params.stack = JSON.stringify(new Error().stack);
|
|
114
|
+
}
|
|
115
|
+
this.add(msg, params, true);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Logs a warn.
|
|
119
|
+
*
|
|
120
|
+
* @param message The message to warn.
|
|
121
|
+
* @param parameters The parameters to send along with the message
|
|
122
|
+
*/
|
|
123
|
+
warn(message, parameters = '') {
|
|
124
|
+
const msg = `[warn] ${message}`;
|
|
125
|
+
this.add(msg, parameters, true);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Logs a hmmm.
|
|
129
|
+
*
|
|
130
|
+
* @param message The message to hmmm.
|
|
131
|
+
* @param parameters The parameters to send along with the message
|
|
132
|
+
*/
|
|
133
|
+
hmmm(message, parameters = '') {
|
|
134
|
+
const msg = `[hmmm] ${message}`;
|
|
135
|
+
this.add(msg, parameters, false);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Logs a message in the browser console.
|
|
139
|
+
*
|
|
140
|
+
* @param message The message to log.
|
|
141
|
+
*/
|
|
142
|
+
client(message, extraData = '') {
|
|
143
|
+
if (!this.clientLoggingCallback) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this.clientLoggingCallback(message, extraData);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import $ from 'jquery';
|
|
2
|
+
import * as Utils from './utils';
|
|
3
|
+
/**
|
|
4
|
+
* Adds our API command to the URL so the API call is more easily identified in the
|
|
5
|
+
* network tab of the JS console
|
|
6
|
+
*
|
|
7
|
+
* @param {string} command
|
|
8
|
+
* @param {string} url
|
|
9
|
+
* @returns {string}
|
|
10
|
+
*/
|
|
11
|
+
function addCommandToUrl(command, url) {
|
|
12
|
+
let newUrl = url;
|
|
13
|
+
if (command) {
|
|
14
|
+
// Add a ? to the end of the URL if there isn't one already
|
|
15
|
+
if (newUrl.indexOf('?') === -1) {
|
|
16
|
+
newUrl = `${newUrl}?`;
|
|
17
|
+
}
|
|
18
|
+
newUrl = `${newUrl}&command=${command}`;
|
|
19
|
+
}
|
|
20
|
+
return newUrl;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* @param {String} endpoint
|
|
24
|
+
*
|
|
25
|
+
* @returns {Object}
|
|
26
|
+
*/
|
|
27
|
+
export default function Network(endpoint) {
|
|
28
|
+
// A flag that turns true when the user navigates away
|
|
29
|
+
let isNavigatingAway = false;
|
|
30
|
+
// If URL ends in `/` we're using /api/{command} format.
|
|
31
|
+
const isNewURLFormat = endpoint[endpoint.length - 1] === '/';
|
|
32
|
+
if (!endpoint) {
|
|
33
|
+
throw new Error('Cannot instantiate Network without an url endpoint');
|
|
34
|
+
}
|
|
35
|
+
// Attach a listener to the event indicating that we're leaving a page
|
|
36
|
+
if (Utils.isWindowAvailable()) {
|
|
37
|
+
window.onbeforeunload = () => {
|
|
38
|
+
isNavigatingAway = true;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
/**
|
|
43
|
+
* @param {String} url to fetch
|
|
44
|
+
* @returns {Deferred}
|
|
45
|
+
*/
|
|
46
|
+
get(url) {
|
|
47
|
+
return $.get(url);
|
|
48
|
+
},
|
|
49
|
+
/**
|
|
50
|
+
* @param {Object} parameters
|
|
51
|
+
*
|
|
52
|
+
* @returns {$.Deferred}
|
|
53
|
+
*/
|
|
54
|
+
post(parameters) {
|
|
55
|
+
// Build request
|
|
56
|
+
let newURL = endpoint;
|
|
57
|
+
if (isNewURLFormat) {
|
|
58
|
+
// Remove command from parameters and use it in the URL
|
|
59
|
+
const command = parameters.command;
|
|
60
|
+
// eslint-disable-next-line no-param-reassign
|
|
61
|
+
delete parameters.command;
|
|
62
|
+
newURL = `${endpoint}${command}`;
|
|
63
|
+
}
|
|
64
|
+
const settings = {
|
|
65
|
+
url: newURL,
|
|
66
|
+
type: 'POST',
|
|
67
|
+
data: parameters,
|
|
68
|
+
};
|
|
69
|
+
const formData = new FormData();
|
|
70
|
+
let shouldUseFormData = false;
|
|
71
|
+
// Add the API command to our URL (for console debugging purposes)
|
|
72
|
+
// Note that parameters.command is empty if we're using the new API format and this will do nothing.
|
|
73
|
+
settings.url = addCommandToUrl(parameters.command, settings.url);
|
|
74
|
+
// Check to see if parameters contains a File or Blob object
|
|
75
|
+
// If it does, we should use formData instead of parameters and update
|
|
76
|
+
// the ajax settings accordingly
|
|
77
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
78
|
+
if (value === undefined) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
// Populate formData in case we need it
|
|
82
|
+
formData.append(key, value);
|
|
83
|
+
if (value instanceof File || value instanceof Blob) {
|
|
84
|
+
shouldUseFormData = true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (shouldUseFormData) {
|
|
88
|
+
settings.processData = false;
|
|
89
|
+
settings.contentType = false;
|
|
90
|
+
settings.data = formData;
|
|
91
|
+
}
|
|
92
|
+
return $.ajax(settings);
|
|
93
|
+
},
|
|
94
|
+
/**
|
|
95
|
+
* Uses the fetch API to send a keepalive request that will complete
|
|
96
|
+
* even if the browser is closed
|
|
97
|
+
*
|
|
98
|
+
* Note: This method ONLY provides partial support for sending complex data structures.
|
|
99
|
+
* It supports a single level array of objects with no nested properties
|
|
100
|
+
* eg. [{one: 1}, {two:2}]
|
|
101
|
+
*
|
|
102
|
+
* @param {Object} parameters
|
|
103
|
+
* @returns {$.Deferred}
|
|
104
|
+
*/
|
|
105
|
+
keepalive(parameters) {
|
|
106
|
+
// Build request
|
|
107
|
+
const settings = {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
keepalive: true,
|
|
110
|
+
credentials: 'same-origin',
|
|
111
|
+
};
|
|
112
|
+
let url = endpoint;
|
|
113
|
+
// Add the API command to our URL (for console debugging purposes)
|
|
114
|
+
url = addCommandToUrl(parameters.command, url);
|
|
115
|
+
// Add our data as form data
|
|
116
|
+
const formData = new FormData();
|
|
117
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
118
|
+
if (value === undefined) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (Array.isArray(value)) {
|
|
122
|
+
for (const [i, valueItem] of value.entries()) {
|
|
123
|
+
if (Utils.isObject(valueItem)) {
|
|
124
|
+
for (const [valueItemObjectKey, valueItemObjectValue] of Object.entries(valueItem)) {
|
|
125
|
+
formData.append(`${key}[${i}][${valueItemObjectKey}]`, valueItemObjectValue);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
formData.append(`${key}[${i}]`, valueItem);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
formData.append(key, value);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
settings.body = formData;
|
|
138
|
+
// Make our request via the fetch API but return it in the form of a jQuery promise
|
|
139
|
+
// so that our API can be consistent
|
|
140
|
+
const promise = new $.Deferred();
|
|
141
|
+
fetch(url, settings)
|
|
142
|
+
.then(() => {
|
|
143
|
+
// No need to return a response since there is no script to process it
|
|
144
|
+
// due to the browser being closed
|
|
145
|
+
promise.resolve();
|
|
146
|
+
})
|
|
147
|
+
.catch((error) => {
|
|
148
|
+
promise.reject(error);
|
|
149
|
+
});
|
|
150
|
+
return promise;
|
|
151
|
+
},
|
|
152
|
+
/**
|
|
153
|
+
* @param {Function} callback
|
|
154
|
+
*/
|
|
155
|
+
registerNetworkFailureHandler(callback) {
|
|
156
|
+
$(document).ajaxError((event, jqxhr) => {
|
|
157
|
+
// Some browsers invoke the ajax error callbacks when navigating away during a pending ajax call
|
|
158
|
+
// Ignore this if navigating away
|
|
159
|
+
if (isNavigatingAway) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const response = jqxhr.responseJSON;
|
|
163
|
+
const jsonCode = response ? parseInt(response.jsonCode, 10) : null;
|
|
164
|
+
callback(jsonCode, response);
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
declare namespace _default {
|
|
2
|
+
/**
|
|
3
|
+
* Converts an exponential number into it's non-exponential string equivalent
|
|
4
|
+
*
|
|
5
|
+
* @param {Number} num
|
|
6
|
+
*
|
|
7
|
+
* @returns {String}
|
|
8
|
+
*/
|
|
9
|
+
function notExponential(num: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* Format a number, similar to PHP's number_format.
|
|
12
|
+
*
|
|
13
|
+
* @param {Number} _a The number you want to format
|
|
14
|
+
* @param {Number} [b="0"] The number of decimal places you want
|
|
15
|
+
* @param {String} [_c=","] The decimal separator
|
|
16
|
+
* @param {String} [d="."] The thousands separator
|
|
17
|
+
*
|
|
18
|
+
* @todo should be camelCase / needs refactor
|
|
19
|
+
* @returns {String}
|
|
20
|
+
*/
|
|
21
|
+
function number_format(_a: number, b?: number, _c?: string, d?: string): string;
|
|
22
|
+
function generateRandom6DigitID(): number;
|
|
23
|
+
/**
|
|
24
|
+
* Converts a number to base 26 (using capital english letters as digits).
|
|
25
|
+
*
|
|
26
|
+
* @param {Number} num The number to convert to base 26.
|
|
27
|
+
*
|
|
28
|
+
* @returns {String} The number, converted to base 26.
|
|
29
|
+
*/
|
|
30
|
+
function toBase26LetterCode(num: number): string;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a number is finite and not NaN. i.e.
|
|
33
|
+
*
|
|
34
|
+
* @param {number} number The number to test
|
|
35
|
+
*
|
|
36
|
+
* @returns {Boolean} true if the number is finite and not NaN.
|
|
37
|
+
*/
|
|
38
|
+
function isFiniteNumber(number: number): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Truncates the given number to the given precision.
|
|
41
|
+
*
|
|
42
|
+
* @param {number} number the number to truncate.
|
|
43
|
+
* @param {number} decimals the number of decimals to keep.
|
|
44
|
+
*
|
|
45
|
+
* @returns {number} the truncated number.
|
|
46
|
+
*/
|
|
47
|
+
function toPrecision(number: number, decimals: number): number;
|
|
48
|
+
/**
|
|
49
|
+
* Check if a number is between 2 numbers, including them.
|
|
50
|
+
*
|
|
51
|
+
* @param {number} number to check
|
|
52
|
+
* @param {number} a the 1st limit
|
|
53
|
+
* @param {number} b the 2nd limit
|
|
54
|
+
*
|
|
55
|
+
* @returns {boolean}
|
|
56
|
+
*/
|
|
57
|
+
function isNumberBetween(number: number, a: number, b: number): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Returns how many decimals to display (used for currencies).
|
|
60
|
+
*
|
|
61
|
+
* @param {Number} rate
|
|
62
|
+
* @returns {Number}
|
|
63
|
+
*/
|
|
64
|
+
function getDisplayDecimals(rate: number): number;
|
|
65
|
+
namespace tax {
|
|
66
|
+
/**
|
|
67
|
+
* Calculate the pre-tax, or net amount
|
|
68
|
+
*
|
|
69
|
+
* @param {Number} total The total to calculate from, in negative cents
|
|
70
|
+
* @param {UserDefinedField} taxUDF The tax UDF
|
|
71
|
+
*
|
|
72
|
+
* @returns {number} The pre-tax amount, in negative cents
|
|
73
|
+
*/
|
|
74
|
+
function calculatePreTaxAmount(total: number, taxUDF: UserDefinedField): number;
|
|
75
|
+
/**
|
|
76
|
+
* Calculate the tax amount from the total.
|
|
77
|
+
*
|
|
78
|
+
* @param {Number} total The total to calculate from
|
|
79
|
+
* @param {String} percentage The percentage, as a string, e.g. '20%'
|
|
80
|
+
*
|
|
81
|
+
* @returns {number} The amount of tax
|
|
82
|
+
*/
|
|
83
|
+
function calculateTaxFromPercentage(total: number, percentage: string): number;
|
|
84
|
+
/**
|
|
85
|
+
* Calculate the tax amount from a divisor.
|
|
86
|
+
*
|
|
87
|
+
* @param {Number} total The total to calculate from
|
|
88
|
+
* @param {Number} divisor The divisor (0.1 = 10%)
|
|
89
|
+
*
|
|
90
|
+
* @returns {number} The amount of tax
|
|
91
|
+
*/
|
|
92
|
+
function calculateTaxFromDivisor(total: number, divisor: number): number;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export default _default;
|