@appium/support
Advanced tools
Comparing version 4.5.0 to 5.0.1
@@ -99,3 +99,2 @@ /// <reference types="node" /> | ||
export type { ExtractAllOptions, ZipEntry, ZipOptions, ZipCompressionOptions, ZipSourceOptions, } from './zip'; | ||
export type { SecureValuePreprocessingRule } from './log-internal'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -0,51 +1,14 @@ | ||
/** | ||
* | ||
* @param {AppiumLoggerPrefix?} [prefix=null] | ||
* @returns {AppiumLogger} | ||
*/ | ||
export function getLogger(prefix?: import("@appium/types").AppiumLoggerPrefix | null | undefined): AppiumLogger; | ||
/** @type {import('@appium/types').AppiumLoggerLevel[]} */ | ||
export const LEVELS: import('@appium/types').AppiumLoggerLevel[]; | ||
export const log: import("@appium/types").AppiumLogger; | ||
export default log; | ||
export type LoadResult = { | ||
/** | ||
* The list of rule parsing issues (one item per rule). | ||
* Rules with issues are skipped. An empty list is returned if no parsing issues exist. | ||
*/ | ||
issues: string[]; | ||
/** | ||
* The list of successfully loaded | ||
* replacement rules. The list could be empty if no rules were loaded. | ||
*/ | ||
rules: import('./log-internal').SecureValuePreprocessingRule[]; | ||
}; | ||
export type AppiumLoggerPrefix = import('@appium/types').AppiumLoggerPrefix; | ||
export type AppiumLogger = import('@appium/types').AppiumLogger; | ||
export type AppiumLoggerLevel = import('@appium/types').AppiumLoggerLevel; | ||
export const log: import("@appium/types").AppiumLogger; | ||
/** | ||
* | ||
* @param {import('@appium/logger').Logger} logger | ||
*/ | ||
export function patchLogger(logger: import('@appium/logger').Logger): void; | ||
/** | ||
* | ||
* @param {AppiumLoggerPrefix?} prefix | ||
* @returns {AppiumLogger} | ||
*/ | ||
export function getLogger(prefix?: AppiumLoggerPrefix | null): AppiumLogger; | ||
/** | ||
* @typedef LoadResult | ||
* @property {string[]} issues The list of rule parsing issues (one item per rule). | ||
* Rules with issues are skipped. An empty list is returned if no parsing issues exist. | ||
* @property {import('./log-internal').SecureValuePreprocessingRule[]} rules The list of successfully loaded | ||
* replacement rules. The list could be empty if no rules were loaded. | ||
*/ | ||
/** | ||
* Loads the JSON file containing secure values replacement rules. | ||
* This might be necessary to hide sensitive values that may possibly | ||
* appear in Appium logs. | ||
* Each call to this method replaces the previously loaded rules if any existed. | ||
* | ||
* @param {string|string[]|import('@appium/types').LogFiltersConfig} rulesJsonPath The full path to the JSON file containing | ||
* the replacement rules. Each rule could either be a string to be replaced | ||
* or an object with predefined properties. | ||
* @throws {Error} If the given file cannot be loaded | ||
* @returns {Promise<LoadResult>} | ||
*/ | ||
export function loadSecureValuesPreprocessingRules(rulesJsonPath: string | string[] | import('@appium/types').LogFiltersConfig): Promise<LoadResult>; | ||
//# sourceMappingURL=logging.d.ts.map |
"use strict"; | ||
// @ts-check | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -7,8 +6,6 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.loadSecureValuesPreprocessingRules = exports.getLogger = exports.patchLogger = exports.log = exports.LEVELS = void 0; | ||
exports.getLogger = exports.log = exports.LEVELS = void 0; | ||
const logger_1 = __importDefault(require("@appium/logger")); | ||
const lodash_1 = __importDefault(require("lodash")); | ||
const util_1 = require("./util"); | ||
const moment_1 = __importDefault(require("moment")); | ||
const log_internal_1 = __importDefault(require("./log-internal")); | ||
/** @type {import('@appium/types').AppiumLoggerLevel[]} */ | ||
@@ -18,63 +15,49 @@ exports.LEVELS = ['silly', 'verbose', 'debug', 'info', 'http', 'warn', 'error']; | ||
const PREFIX_TIMESTAMP_FORMAT = 'HH-mm-ss:SSS'; | ||
// mock log object used in testing mode | ||
let mockLog = {}; | ||
for (let level of exports.LEVELS) { | ||
mockLog[level] = () => { }; | ||
} | ||
// export a default logger with no prefix | ||
exports.log = getLogger(); | ||
// mock log object is used in testing mode to silence the output | ||
const MOCK_LOG = { | ||
unwrap: () => ({ | ||
loadSecureValuesPreprocessingRules: () => ({ | ||
issues: [], | ||
rules: [], | ||
}), | ||
level: 'verbose', | ||
prefix: '', | ||
log: lodash_1.default.noop, | ||
}), | ||
...(lodash_1.default.fromPairs(exports.LEVELS.map((l) => [l, lodash_1.default.noop]))), | ||
}; | ||
/** | ||
* | ||
* @param {import('@appium/logger').Logger} logger | ||
*/ | ||
function patchLogger(logger) { | ||
if (!logger.debug) { | ||
logger.addLevel('debug', 1000, { fg: 'blue', bg: 'black' }, 'dbug'); | ||
} | ||
} | ||
exports.patchLogger = patchLogger; | ||
/** | ||
* | ||
* @returns {[import('@appium/logger').Logger, boolean]} | ||
*/ | ||
function _getLogger() { | ||
// check if the user set the `_TESTING` or `_FORCE_LOGS` flag | ||
const testingMode = process.env._TESTING === '1'; | ||
const forceLogMode = process.env._FORCE_LOGS === '1'; | ||
// if is possible that there is a logger instance that is already around, | ||
// in which case we want t o use that | ||
const usingGlobalLog = !!global._global_npmlog; | ||
let logger; | ||
if (testingMode && !forceLogMode) { | ||
// in testing mode, use a mock logger object that we can query | ||
logger = mockLog; | ||
} | ||
else { | ||
// otherwise, either use the global, or a new `npmlog` object | ||
logger = global._global_npmlog || logger_1.default; | ||
// The default value is 10000, which causes excessive memory usage | ||
logger.maxRecordSize = MAX_LOG_RECORDS_COUNT; | ||
} | ||
patchLogger(logger); | ||
return [logger, usingGlobalLog]; | ||
} | ||
/** | ||
* @param {AppiumLoggerPrefix?} prefix | ||
* @param {boolean} logTimestamp whether to include timestamps into log prefixes | ||
* @returns {string} | ||
*/ | ||
function getActualPrefix(prefix, logTimestamp = false) { | ||
const result = (lodash_1.default.isFunction(prefix) ? prefix() : prefix) ?? ''; | ||
return logTimestamp ? `[${(0, moment_1.default)().format(PREFIX_TIMESTAMP_FORMAT)}] ${result}` : result; | ||
} | ||
/** | ||
* | ||
* @param {AppiumLoggerPrefix?} prefix | ||
* @param {AppiumLoggerPrefix?} [prefix=null] | ||
* @returns {AppiumLogger} | ||
*/ | ||
function getLogger(prefix = null) { | ||
let [logger, usingGlobalLog] = _getLogger(); | ||
const [logger, usingGlobalLog] = _getLogger(); | ||
// wrap the logger so that we can catch and modify any logging | ||
let wrappedLogger = { | ||
const wrappedLogger = { | ||
unwrap: () => logger, | ||
levels: exports.LEVELS, | ||
prefix, | ||
/** | ||
* Logs given arguments at the error level and returns | ||
* the error object. | ||
* | ||
* @param {...any} args | ||
* @returns {Error} | ||
*/ | ||
errorWithException(/** @type {any[]} */ ...args) { | ||
this.error(...args); | ||
// make sure we have an `Error` object. Wrap if necessary | ||
return lodash_1.default.isError(args[0]) ? args[0] : new Error(args.join('\n')); | ||
}, | ||
/** | ||
* @deprecated Use {@link errorWithException} instead | ||
* @param {...any} args | ||
* @throws {Error} | ||
*/ | ||
errorAndThrow(/** @type {any[]} */ ...args) { | ||
throw this.errorWithException(args); | ||
}, | ||
}; | ||
@@ -92,29 +75,11 @@ // allow access to the level of the underlying logger | ||
}); | ||
const logTimestamp = process.env._LOG_TIMESTAMP === '1'; | ||
const isDebugTimestampLoggingEnabled = process.env._LOG_TIMESTAMP === '1'; | ||
// add all the levels from `npmlog`, and map to the underlying logger | ||
for (const level of exports.LEVELS) { | ||
wrappedLogger[level] = /** @param {...any} args */ function (...args) { | ||
const actualPrefix = getActualPrefix(this.prefix, logTimestamp); | ||
for (const arg of args) { | ||
const out = lodash_1.default.isError(arg) && arg.stack ? arg.stack : `${arg}`; | ||
for (const line of out.split('\n')) { | ||
// it is necessary to unleak each line because `split` call | ||
// creates "views" to the original string as well as the `substring` one | ||
const unleakedLine = (0, util_1.unleakString)(line); | ||
logger[level](actualPrefix, log_internal_1.default.preprocess(unleakedLine)); | ||
} | ||
} | ||
wrappedLogger[level] = /** @param {any[]} args */ function (...args) { | ||
const finalPrefix = getFinalPrefix(this.prefix, isDebugTimestampLoggingEnabled); | ||
// @ts-ignore This is OK | ||
logger[level](finalPrefix, ...args); | ||
}; | ||
} | ||
wrappedLogger.errorWithException = function (/** @type {any[]} */ ...args) { | ||
this.error(...args); | ||
// make sure we have an `Error` object. Wrap if necessary | ||
return lodash_1.default.isError(args[0]) ? args[0] : new Error(args.map(util_1.unleakString).join('\n')); | ||
}; | ||
/** | ||
* @deprecated Use {@link errorWithException} instead | ||
*/ | ||
wrappedLogger.errorAndThrow = function (/** @type {any[]} */ ...args) { | ||
throw this.errorWithException(args); | ||
}; | ||
if (!usingGlobalLog) { | ||
@@ -130,32 +95,35 @@ // if we're not using a global log specified from some top-level package, | ||
/** | ||
* @typedef LoadResult | ||
* @property {string[]} issues The list of rule parsing issues (one item per rule). | ||
* Rules with issues are skipped. An empty list is returned if no parsing issues exist. | ||
* @property {import('./log-internal').SecureValuePreprocessingRule[]} rules The list of successfully loaded | ||
* replacement rules. The list could be empty if no rules were loaded. | ||
* | ||
* @returns {[import('@appium/logger').Logger, boolean]} | ||
*/ | ||
function _getLogger() { | ||
// check if the user set the `_TESTING` or `_FORCE_LOGS` flag | ||
const testingMode = process.env._TESTING === '1'; | ||
const forceLogMode = process.env._FORCE_LOGS === '1'; | ||
// if is possible that there is a logger instance that is already around, | ||
// in which case we want t o use that | ||
const useGlobalLog = !!global._global_npmlog; | ||
const logger = testingMode && !forceLogMode | ||
// in testing mode, use a mock logger object that we can query | ||
? MOCK_LOG | ||
// otherwise, either use the global, or a new `npmlog` object | ||
: (global._global_npmlog || logger_1.default); | ||
// The default value is 10000, which causes excessive memory usage | ||
logger.maxRecordSize = MAX_LOG_RECORDS_COUNT; | ||
return [logger, useGlobalLog]; | ||
} | ||
/** | ||
* Loads the JSON file containing secure values replacement rules. | ||
* This might be necessary to hide sensitive values that may possibly | ||
* appear in Appium logs. | ||
* Each call to this method replaces the previously loaded rules if any existed. | ||
* | ||
* @param {string|string[]|import('@appium/types').LogFiltersConfig} rulesJsonPath The full path to the JSON file containing | ||
* the replacement rules. Each rule could either be a string to be replaced | ||
* or an object with predefined properties. | ||
* @throws {Error} If the given file cannot be loaded | ||
* @returns {Promise<LoadResult>} | ||
* @param {AppiumLoggerPrefix?} prefix | ||
* @param {boolean} [shouldLogTimestamp=false] whether to include timestamps into log prefixes | ||
* @returns {string} | ||
*/ | ||
async function loadSecureValuesPreprocessingRules(rulesJsonPath) { | ||
const issues = await log_internal_1.default.loadRules(rulesJsonPath); | ||
return { | ||
issues, | ||
rules: lodash_1.default.cloneDeep(log_internal_1.default.rules), | ||
}; | ||
function getFinalPrefix(prefix, shouldLogTimestamp = false) { | ||
const result = (lodash_1.default.isFunction(prefix) ? prefix() : prefix) ?? ''; | ||
if (!shouldLogTimestamp) { | ||
return result; | ||
} | ||
const formattedTimestamp = `[${(0, moment_1.default)().format(PREFIX_TIMESTAMP_FORMAT)}]`; | ||
return result ? `${formattedTimestamp} ${result}` : formattedTimestamp; | ||
} | ||
exports.loadSecureValuesPreprocessingRules = loadSecureValuesPreprocessingRules; | ||
// export a default logger with no prefix | ||
const log = getLogger(); | ||
exports.log = log; | ||
exports.default = log; | ||
exports.default = exports.log; | ||
/** | ||
@@ -162,0 +130,0 @@ * @typedef {import('@appium/types').AppiumLoggerPrefix} AppiumLoggerPrefix |
@@ -141,11 +141,2 @@ /** | ||
/** | ||
* This function is necessary to workaround unexpected memory leaks | ||
* caused by NodeJS string interning | ||
* behavior described in https://bugs.chromium.org/p/v8/issues/detail?id=2869 | ||
* | ||
* @param {any} s - The string to unleak | ||
* @return {string} Either the unleaked string or the original object converted to string | ||
*/ | ||
export function unleakString(s: any): string; | ||
/** | ||
* Stringifies the object passed in, converting Buffers into Strings for better | ||
@@ -152,0 +143,0 @@ * display. This mimics JSON.stringify (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) |
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getLockFileGuard = exports.shellParse = exports.uuidV5 = exports.uuidV4 = exports.uuidV3 = exports.uuidV1 = exports.toInMemoryBase64 = exports.KiB = exports.MiB = exports.GiB = exports.pluralize = exports.jsonStringify = exports.unleakString = exports.quote = exports.coerceVersion = exports.compareVersions = exports.isSameDestination = exports.W3C_WEB_ELEMENT_IDENTIFIER = exports.isSubPath = exports.toReadableSizeString = exports.filterObject = exports.unwrapElement = exports.wrapElement = exports.safeJsonParse = exports.multiResolve = exports.cancellableDelay = exports.localIp = exports.escapeSpecialChars = exports.escapeSpace = exports.hasValue = exports.hasContent = void 0; | ||
exports.getLockFileGuard = exports.shellParse = exports.uuidV5 = exports.uuidV4 = exports.uuidV3 = exports.uuidV1 = exports.toInMemoryBase64 = exports.KiB = exports.MiB = exports.GiB = exports.pluralize = exports.jsonStringify = exports.quote = exports.coerceVersion = exports.compareVersions = exports.isSameDestination = exports.W3C_WEB_ELEMENT_IDENTIFIER = exports.isSubPath = exports.toReadableSizeString = exports.filterObject = exports.unwrapElement = exports.wrapElement = exports.safeJsonParse = exports.multiResolve = exports.cancellableDelay = exports.localIp = exports.escapeSpecialChars = exports.escapeSpace = exports.hasValue = exports.hasContent = void 0; | ||
const bluebird_1 = __importDefault(require("bluebird")); | ||
@@ -355,14 +355,2 @@ const lodash_1 = __importDefault(require("lodash")); | ||
/** | ||
* This function is necessary to workaround unexpected memory leaks | ||
* caused by NodeJS string interning | ||
* behavior described in https://bugs.chromium.org/p/v8/issues/detail?id=2869 | ||
* | ||
* @param {any} s - The string to unleak | ||
* @return {string} Either the unleaked string or the original object converted to string | ||
*/ | ||
function unleakString(s) { | ||
return ` ${s}`.substring(1); | ||
} | ||
exports.unleakString = unleakString; | ||
/** | ||
* @typedef PluralizeOptions | ||
@@ -369,0 +357,0 @@ * @property {boolean} [inclusive=false] - Whether to prefix with the number (e.g., 3 ducks) |
@@ -83,2 +83,1 @@ import * as tempDir from './tempdir'; | ||
} from './zip'; | ||
export type {SecureValuePreprocessingRule} from './log-internal'; |
@@ -1,8 +0,4 @@ | ||
// @ts-check | ||
import globalLog from '@appium/logger'; | ||
import _ from 'lodash'; | ||
import {unleakString} from './util'; | ||
import moment from 'moment'; | ||
import SECURE_VALUES_PREPROCESSOR from './log-internal'; | ||
@@ -12,72 +8,53 @@ /** @type {import('@appium/types').AppiumLoggerLevel[]} */ | ||
const MAX_LOG_RECORDS_COUNT = 3000; | ||
const PREFIX_TIMESTAMP_FORMAT = 'HH-mm-ss:SSS'; | ||
// export a default logger with no prefix | ||
export const log = getLogger(); | ||
// mock log object is used in testing mode to silence the output | ||
const MOCK_LOG = { | ||
unwrap: () => ({ | ||
loadSecureValuesPreprocessingRules: () => ({ | ||
issues: [], | ||
rules: [], | ||
}), | ||
level: 'verbose', | ||
prefix: '', | ||
log: _.noop, | ||
}), | ||
...(_.fromPairs(LEVELS.map((l) => [l, _.noop]))), | ||
}; | ||
// mock log object used in testing mode | ||
let mockLog = {}; | ||
for (let level of LEVELS) { | ||
mockLog[level] = () => {}; | ||
} | ||
/** | ||
* | ||
* @param {import('@appium/logger').Logger} logger | ||
*/ | ||
function patchLogger(logger) { | ||
if (!logger.debug) { | ||
logger.addLevel('debug', 1000, {fg: 'blue', bg: 'black'}, 'dbug'); | ||
} | ||
} | ||
/** | ||
* | ||
* @returns {[import('@appium/logger').Logger, boolean]} | ||
*/ | ||
function _getLogger() { | ||
// check if the user set the `_TESTING` or `_FORCE_LOGS` flag | ||
const testingMode = process.env._TESTING === '1'; | ||
const forceLogMode = process.env._FORCE_LOGS === '1'; | ||
// if is possible that there is a logger instance that is already around, | ||
// in which case we want t o use that | ||
const usingGlobalLog = !!global._global_npmlog; | ||
let logger; | ||
if (testingMode && !forceLogMode) { | ||
// in testing mode, use a mock logger object that we can query | ||
logger = mockLog; | ||
} else { | ||
// otherwise, either use the global, or a new `npmlog` object | ||
logger = global._global_npmlog || globalLog; | ||
// The default value is 10000, which causes excessive memory usage | ||
logger.maxRecordSize = MAX_LOG_RECORDS_COUNT; | ||
} | ||
patchLogger(logger); | ||
return [logger, usingGlobalLog]; | ||
} | ||
/** | ||
* @param {AppiumLoggerPrefix?} prefix | ||
* @param {boolean} logTimestamp whether to include timestamps into log prefixes | ||
* @returns {string} | ||
*/ | ||
function getActualPrefix(prefix, logTimestamp = false) { | ||
const result = (_.isFunction(prefix) ? prefix() : prefix) ?? ''; | ||
return logTimestamp ? `[${moment().format(PREFIX_TIMESTAMP_FORMAT)}] ${result}` : result; | ||
} | ||
/** | ||
* | ||
* @param {AppiumLoggerPrefix?} prefix | ||
* @param {AppiumLoggerPrefix?} [prefix=null] | ||
* @returns {AppiumLogger} | ||
*/ | ||
function getLogger(prefix = null) { | ||
let [logger, usingGlobalLog] = _getLogger(); | ||
export function getLogger(prefix = null) { | ||
const [logger, usingGlobalLog] = _getLogger(); | ||
// wrap the logger so that we can catch and modify any logging | ||
let wrappedLogger = { | ||
const wrappedLogger = { | ||
unwrap: () => logger, | ||
levels: LEVELS, | ||
prefix, | ||
/** | ||
* Logs given arguments at the error level and returns | ||
* the error object. | ||
* | ||
* @param {...any} args | ||
* @returns {Error} | ||
*/ | ||
errorWithException (/** @type {any[]} */ ...args) { | ||
this.error(...args); | ||
// make sure we have an `Error` object. Wrap if necessary | ||
return _.isError(args[0]) ? args[0] : new Error(args.join('\n')); | ||
}, | ||
/** | ||
* @deprecated Use {@link errorWithException} instead | ||
* @param {...any} args | ||
* @throws {Error} | ||
*/ | ||
errorAndThrow (/** @type {any[]} */ ...args) { | ||
throw this.errorWithException(args); | ||
}, | ||
}; | ||
// allow access to the level of the underlying logger | ||
@@ -94,31 +71,11 @@ Object.defineProperty(wrappedLogger, 'level', { | ||
}); | ||
const logTimestamp = process.env._LOG_TIMESTAMP === '1'; | ||
const isDebugTimestampLoggingEnabled = process.env._LOG_TIMESTAMP === '1'; | ||
// add all the levels from `npmlog`, and map to the underlying logger | ||
for (const level of LEVELS) { | ||
wrappedLogger[level] = /** @param {...any} args */ function (...args) { | ||
const actualPrefix = getActualPrefix(this.prefix, logTimestamp); | ||
for (const arg of args) { | ||
const out = _.isError(arg) && arg.stack ? arg.stack : `${arg}`; | ||
for (const line of out.split('\n')) { | ||
// it is necessary to unleak each line because `split` call | ||
// creates "views" to the original string as well as the `substring` one | ||
const unleakedLine = unleakString(line); | ||
logger[level](actualPrefix, SECURE_VALUES_PREPROCESSOR.preprocess(unleakedLine)); | ||
} | ||
} | ||
wrappedLogger[level] = /** @param {any[]} args */ function (...args) { | ||
const finalPrefix = getFinalPrefix(this.prefix, isDebugTimestampLoggingEnabled); | ||
// @ts-ignore This is OK | ||
logger[level](finalPrefix, ...args); | ||
}; | ||
} | ||
wrappedLogger.errorWithException = function (/** @type {any[]} */ ...args) { | ||
this.error(...args); | ||
// make sure we have an `Error` object. Wrap if necessary | ||
return _.isError(args[0]) ? args[0] : new Error(args.map(unleakString).join('\n')); | ||
}; | ||
/** | ||
* @deprecated Use {@link errorWithException} instead | ||
*/ | ||
wrappedLogger.errorAndThrow = function (/** @type {any[]} */ ...args) { | ||
throw this.errorWithException(args); | ||
}; | ||
if (!usingGlobalLog) { | ||
@@ -134,33 +91,36 @@ // if we're not using a global log specified from some top-level package, | ||
/** | ||
* @typedef LoadResult | ||
* @property {string[]} issues The list of rule parsing issues (one item per rule). | ||
* Rules with issues are skipped. An empty list is returned if no parsing issues exist. | ||
* @property {import('./log-internal').SecureValuePreprocessingRule[]} rules The list of successfully loaded | ||
* replacement rules. The list could be empty if no rules were loaded. | ||
* | ||
* @returns {[import('@appium/logger').Logger, boolean]} | ||
*/ | ||
function _getLogger() { | ||
// check if the user set the `_TESTING` or `_FORCE_LOGS` flag | ||
const testingMode = process.env._TESTING === '1'; | ||
const forceLogMode = process.env._FORCE_LOGS === '1'; | ||
// if is possible that there is a logger instance that is already around, | ||
// in which case we want t o use that | ||
const useGlobalLog = !!global._global_npmlog; | ||
const logger = testingMode && !forceLogMode | ||
// in testing mode, use a mock logger object that we can query | ||
? MOCK_LOG | ||
// otherwise, either use the global, or a new `npmlog` object | ||
: (global._global_npmlog || globalLog); | ||
// The default value is 10000, which causes excessive memory usage | ||
logger.maxRecordSize = MAX_LOG_RECORDS_COUNT; | ||
return [logger, useGlobalLog]; | ||
} | ||
/** | ||
* Loads the JSON file containing secure values replacement rules. | ||
* This might be necessary to hide sensitive values that may possibly | ||
* appear in Appium logs. | ||
* Each call to this method replaces the previously loaded rules if any existed. | ||
* | ||
* @param {string|string[]|import('@appium/types').LogFiltersConfig} rulesJsonPath The full path to the JSON file containing | ||
* the replacement rules. Each rule could either be a string to be replaced | ||
* or an object with predefined properties. | ||
* @throws {Error} If the given file cannot be loaded | ||
* @returns {Promise<LoadResult>} | ||
* @param {AppiumLoggerPrefix?} prefix | ||
* @param {boolean} [shouldLogTimestamp=false] whether to include timestamps into log prefixes | ||
* @returns {string} | ||
*/ | ||
async function loadSecureValuesPreprocessingRules(rulesJsonPath) { | ||
const issues = await SECURE_VALUES_PREPROCESSOR.loadRules(rulesJsonPath); | ||
return { | ||
issues, | ||
rules: _.cloneDeep(SECURE_VALUES_PREPROCESSOR.rules), | ||
}; | ||
function getFinalPrefix(prefix, shouldLogTimestamp = false) { | ||
const result = (_.isFunction(prefix) ? prefix() : prefix) ?? ''; | ||
if (!shouldLogTimestamp) { | ||
return result; | ||
} | ||
const formattedTimestamp = `[${moment().format(PREFIX_TIMESTAMP_FORMAT)}]`; | ||
return result ? `${formattedTimestamp} ${result}` : formattedTimestamp; | ||
} | ||
// export a default logger with no prefix | ||
const log = getLogger(); | ||
export {log, patchLogger, getLogger, loadSecureValuesPreprocessingRules}; | ||
export default log; | ||
@@ -167,0 +127,0 @@ |
@@ -362,14 +362,2 @@ import B from 'bluebird'; | ||
/** | ||
* This function is necessary to workaround unexpected memory leaks | ||
* caused by NodeJS string interning | ||
* behavior described in https://bugs.chromium.org/p/v8/issues/detail?id=2869 | ||
* | ||
* @param {any} s - The string to unleak | ||
* @return {string} Either the unleaked string or the original object converted to string | ||
*/ | ||
function unleakString(s) { | ||
return ` ${s}`.substring(1); | ||
} | ||
/** | ||
* @typedef PluralizeOptions | ||
@@ -559,3 +547,2 @@ * @property {boolean} [inclusive=false] - Whether to prefix with the number (e.g., 3 ducks) | ||
quote, | ||
unleakString, | ||
jsonStringify, | ||
@@ -562,0 +549,0 @@ pluralize, |
{ | ||
"name": "@appium/support", | ||
"version": "4.5.0", | ||
"version": "5.0.1", | ||
"description": "Support libs used across appium packages", | ||
@@ -44,5 +44,5 @@ "keywords": [ | ||
"dependencies": { | ||
"@appium/logger": "^1.3.0", | ||
"@appium/logger": "^1.4.1", | ||
"@appium/tsconfig": "^0.3.3", | ||
"@appium/types": "^0.19.2", | ||
"@appium/types": "^0.20.1", | ||
"@colors/colors": "1.6.0", | ||
@@ -93,3 +93,3 @@ "@types/archiver": "6.0.2", | ||
"teen_process": "2.1.4", | ||
"type-fest": "4.19.0", | ||
"type-fest": "4.20.0", | ||
"uuid": "9.0.1", | ||
@@ -109,3 +109,3 @@ "which": "4.0.0", | ||
}, | ||
"gitHead": "d4ce2a82d9b70af7cecf5174ec2521b0911f737d" | ||
"gitHead": "192f1f379301539540aa7882f4b667a802cbc4a8" | ||
} |
@@ -54,3 +54,2 @@ # @appium/support | ||
|image-util|Utilities to work with images. Use [sharp](https://github.com/lovell/sharp) under the hood.<br>:bangbang: Node >=18.17 is required to use these utilities| | ||
|log-internal|Utilities needed for internal Appium log config assistance| | ||
|logging|See [the logging section below](#logging)| | ||
@@ -57,0 +56,0 @@ |mjpeg|Helpers needed to implement [MJPEG streaming](https://en.wikipedia.org/wiki/Motion_JPEG#Video_streaming)| |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
409861
105
8366
162
+ Added@appium/schema@0.6.1(transitive)
+ Added@appium/types@0.20.3(transitive)
+ Addedis-core-module@2.15.1(transitive)
+ Addedreadable-stream@4.5.2(transitive)
+ Addedresolve@1.22.8(transitive)
+ Addedtext-decoder@1.2.2(transitive)
+ Addedtype-fest@4.20.0(transitive)
- Removed@appium/schema@0.5.0(transitive)
- Removed@appium/types@0.19.2(transitive)
- Removedis-core-module@2.16.0(transitive)
- Removedreadable-stream@4.6.0(transitive)
- Removedresolve@1.22.9(transitive)
- Removedtext-decoder@1.2.3(transitive)
- Removedtype-fest@4.19.0(transitive)
Updated@appium/logger@^1.4.1
Updated@appium/types@^0.20.1
Updatedtype-fest@4.20.0