@dbux/common
Advanced tools
| import Enum from '../../util/Enum'; | ||
| /** | ||
| * | ||
| */ | ||
| let specialDynamicTraceType = { | ||
| /** | ||
| * It is used to categorize its contexts as a callback of a built-in array higher order function, | ||
| * such as `forEach`, `map`, `find`, `some`, `every` etc. | ||
| * | ||
| * For these contexts: The first parameter is an individual array entry, and the second its index. | ||
| * (If the function defines these parameters.) | ||
| */ | ||
| ArrayHofCall: 1, | ||
| }; | ||
| /** | ||
| * @type {(Enum|typeof specialDynamicTraceType)} | ||
| */ | ||
| const SpecialDynamicTraceType = new Enum(specialDynamicTraceType); | ||
| export default SpecialDynamicTraceType; |
| import isString from 'lodash/isString'; | ||
| /** | ||
| * @see https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_globals_d_.nodejs.callsite.html | ||
| * @see https://github.com/dougwilson/nodejs-depd/blob/master/index.js#L267 | ||
| */ | ||
| function callSite2String(callSite) { | ||
| let file = callSite.getFileName() || '<anonymous>'; | ||
| const line = callSite.getLineNumber(); | ||
| const col = callSite.getColumnNumber(); | ||
| if (callSite.isEval()) { | ||
| file = callSite.getEvalOrigin() + ', ' + file; | ||
| } | ||
| // site.callSite = callSite; | ||
| const fname = callSite.getFunctionName(); | ||
| return `at ${fname} (${file}:${line}:${col})`; | ||
| } | ||
| // eslint-disable-next-line no-inner-declarations | ||
| export function err2String(err) { | ||
| if (Array.isArray(err?.stack)) { | ||
| /** | ||
| * stack is array of `CallSite` | ||
| */ | ||
| return `${err.message}\n ${err.stack.map(callSite2String).join('\n ')}`; | ||
| } | ||
| return isString(err?.stack) && err.stack.includes(err.message) ? err.stack : err.toString(); | ||
| } |
| import isObject from 'lodash/isObject'; | ||
| function joinPath(a, b) { | ||
| if (a) { | ||
| return a + '.' + b; | ||
| } | ||
| return b; | ||
| } | ||
| /** | ||
| * Iterates given object using DFS and Object.keys. | ||
| * @return The first path of a nested prop that matches the given predicate. | ||
| */ | ||
| export function findPathInObject(o, predicate, parentPath = '') { | ||
| if (Array.isArray()) { | ||
| return findPathArray(o, predicate, parentPath); | ||
| } | ||
| else { | ||
| return findPathPlainObject(o, predicate, parentPath); | ||
| } | ||
| } | ||
| function findPathArray(arr, predicate, parentPath) { | ||
| for (let i = 0; i < arr.length; ++i) { | ||
| const value = arr[i]; | ||
| const path = joinPath(parentPath, i); | ||
| if (predicate(value)) { | ||
| return path; | ||
| } | ||
| if (isObject(value)) { | ||
| const result = findPathInObject(value, predicate, path); | ||
| if (result) { | ||
| return result; | ||
| } | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| /** | ||
| * Iterates given object using Object.keys. | ||
| * NOTES: | ||
| * * Object.keys is also how msgPack iterates, but its different from how dbux does it. | ||
| * * Our valueCollection, on the other, hand uses the a simple for loop instead because it reveals a lot more props than Object.keys. | ||
| */ | ||
| function findPathPlainObject(o, predicate, parentPath) { | ||
| const keys = Object.keys(o); | ||
| for (const key of keys) { | ||
| const value = o[key]; | ||
| const path = joinPath(parentPath, key); | ||
| if (predicate(value, key, parentPath)) { | ||
| return path; | ||
| } | ||
| if (isObject(value)) { | ||
| const result = findPathInObject(value, predicate, path); | ||
| if (result) { | ||
| return result; | ||
| } | ||
| } | ||
| } | ||
| return null; | ||
| } |
+3
-3
| { | ||
| "name": "@dbux/common", | ||
| "version": "0.6.8", | ||
| "version": "0.6.9-dev.1", | ||
| "description": "", | ||
@@ -12,3 +12,3 @@ "module": "src/index.js", | ||
| "dependencies": { | ||
| "colors": "^1.4.0", | ||
| "colors": "1.4.0", | ||
| "i18next": "^19.8.2", | ||
@@ -20,3 +20,3 @@ "lodash": "^4.17.21", | ||
| "_moduleAliases": {}, | ||
| "gitHead": "783138f2b391bbdbc25feffb1435ab0b6b307fe8" | ||
| "gitHead": "4b886d820309cfb7e1505e9d6bb83bc1eac0d7ba" | ||
| } |
+15
-3
@@ -0,2 +1,4 @@ | ||
| import isString from 'lodash/isString'; | ||
| import NanoEvents from 'nanoevents'; | ||
| import { err2String } from '../util/errorLog'; | ||
| import { consoleOutputStreams } from '../console'; | ||
@@ -28,3 +30,3 @@ | ||
| // floodGateTimer = null; | ||
| reportUnchecked('error', `Floodgate lifted. Muted ${nGatedReports} reports in the past ${MinSecondsPerReport} seconds.`); | ||
| loglog('Error floodgate', `Floodgate lifted. Muted ${nGatedReports} reports in the past ${MinSecondsPerReport} seconds.`); | ||
| } | ||
@@ -41,3 +43,3 @@ nGatedReports = 0; | ||
| floodGateReported = true; | ||
| reportUnchecked('error', `Error reporting muted due to possibly error flood.`); | ||
| reportUnchecked('error', `[Error floodgate] reporting muted due to possibly error flood.`); | ||
| } | ||
@@ -191,3 +193,13 @@ return; | ||
| newOutputStreams.error = (...args) => { | ||
| args = args.map(arg => arg instanceof Error ? arg.stack : arg); | ||
| args = args.map(arg => { | ||
| if (arg instanceof Error) { | ||
| arg = err2String(arg); | ||
| } | ||
| if (!isString(arg)) { | ||
| arg = arg + ''; | ||
| } | ||
| return arg; | ||
| }); | ||
| cb(...args); | ||
@@ -194,0 +206,0 @@ }; |
+23
-11
@@ -23,3 +23,3 @@ /** | ||
| import { newLogger } from '@dbux/common/src/log/logger'; | ||
| import { startPrettyTimer } from '@dbux/common-node/src/util/timeUtil'; | ||
| import { startPrettyTimer, PrettyTimer } from '@dbux/common-node/src/util/timeUtil'; | ||
@@ -47,2 +47,5 @@ // eslint-disable-next-line no-unused-vars | ||
| return encode(input.toString()); | ||
| // case 'function': | ||
| // warn(`[ENCODE] trying to encode invalid type "${t}":`, input, `(${input.toString()})`); | ||
| // return encode(input.toString()); | ||
| default: | ||
@@ -74,3 +77,3 @@ // don't return anything -> so the default mechanisms can take care of it | ||
| var PacketType = (exports.PacketType = { | ||
| const PacketType = (exports.PacketType = { | ||
| CONNECT: 0, | ||
@@ -83,3 +86,3 @@ DISCONNECT: 1, | ||
| var isInteger = | ||
| const isInteger = | ||
| Number.isInteger || | ||
@@ -94,16 +97,25 @@ function (value) { | ||
| var isString = function (value) { | ||
| function isString(value) { | ||
| return typeof value === 'string'; | ||
| }; | ||
| } | ||
| var isObject = function (value) { | ||
| function isObject(value) { | ||
| return Object.prototype.toString.call(value) === '[object Object]'; | ||
| }; | ||
| } | ||
| function Encoder() { } | ||
| /** | ||
| * @param {*} what | ||
| * @param {PrettyTimer} timer | ||
| * @param {*} buffer | ||
| */ | ||
| function printTimer(what, timer, buffer) { | ||
| // if (buffer.length > 1e8) { | ||
| const msg = buffer.length > 1e8 ? ' (buffer NOT SMALL)' : ''; | ||
| timer.print(debug, `${what}${msg}: ${Math.round(buffer.length / 1000).toLocaleString('en-us')} kb`); | ||
| const seconds = timer.getFinalTimeSeconds(); | ||
| if (seconds > 0.5) { | ||
| let msg = buffer.length > 1e8 ? ' (buffer NOT SMALL)' : ''; | ||
| const time = `${seconds.toFixed(2)}s`; | ||
| debug(`[perf] SLOW ${what}${msg}: ${time}, ${Math.round(buffer.length / 1000).toLocaleString('en-us')}kb`); | ||
| } | ||
| // } | ||
@@ -115,6 +127,6 @@ } | ||
| const timer = startPrettyTimer(); | ||
| // const timer = startPrettyTimer(); | ||
| const encoded = [encoder.encode(packet)]; | ||
| // const s = timer.getFinalTimeSeconds(); | ||
| printTimer('ENCODE', timer, encoded[0]); | ||
| // printTimer('ENCODE', timer, encoded[0]); | ||
@@ -121,0 +133,0 @@ return encoded; |
@@ -8,6 +8,8 @@ import Enum from '../../util/Enum'; | ||
| Reject: 4, | ||
| All: 5, | ||
| Promisify: 6, | ||
| Race: 7, | ||
| Any: 8 | ||
| PromisifyResolve: 5, | ||
| PromisifiedPromise: 6, | ||
| All: 7, | ||
| AllSettled: 8, | ||
| Race: 9, | ||
| Any: 10 | ||
| }; | ||
@@ -14,0 +16,0 @@ |
@@ -6,3 +6,10 @@ import Enum from '../../util/Enum'; | ||
| Module: 1, | ||
| /** | ||
| * Linked against {@link SpecialObjectType}. | ||
| * TODO: Does not seem like we are using this? | ||
| */ | ||
| Arguments: 2, | ||
| /** | ||
| * TODO: Does not seem like we are using this? | ||
| */ | ||
| Undefined: 3, | ||
@@ -9,0 +16,0 @@ Eval: 4, |
| import Enum from '../../util/Enum'; | ||
| /** | ||
| * Warning: some of these are mapped from `SpecialIdentifierType` | ||
| * WARNING: some of these are mapped from `SpecialIdentifierType` | ||
| * {@link TraceCollection#registerValueRefSpecialObjectType} | ||
@@ -6,0 +6,0 @@ */ |
@@ -85,3 +85,4 @@ import isString from 'lodash/isString'; | ||
| Shortened: 2, | ||
| ValueDisabled: 3 | ||
| ValueDisabled: 3, | ||
| ReadError: 4 | ||
| }; | ||
@@ -88,0 +89,0 @@ |
@@ -99,4 +99,5 @@ /** | ||
| /** | ||
| * If this DataNode has a value, this will be `true`. | ||
| * If this DataNode has a primitive value (i.e. `#value` has been assigned), this will be `true`. | ||
| * We track this separately, since `value` might get converted from `undefined` to null by encoder. | ||
| * Use `DataProvider.util.hasAnyValue` to determine whether there is any value associated with this node in general. | ||
| * @type {boolean?} | ||
@@ -103,0 +104,0 @@ */ |
@@ -26,2 +26,3 @@ import ExecutionContextType from './constants/ExecutionContextType'; | ||
| /** | ||
| * @deprecated Use `rootContextId` instead. NOTE: `trace` has it, context did not need it quite yet. | ||
| * @type {number} | ||
@@ -97,2 +98,14 @@ */ | ||
| asyncPromiseId; | ||
| /** | ||
| * @type {{callerPromiseId: number}?} | ||
| */ | ||
| data; | ||
| /** | ||
| * Set to id of promise whose ctor executor was on stack (if any). | ||
| * | ||
| * @type {number?} | ||
| */ | ||
| promisifyId; | ||
| } |
@@ -51,5 +51,5 @@ import PromiseLinkType from './constants/PromiseLinkType'; | ||
| * NOTE: This is only set if `resolve` was called asynchronously. | ||
| * NOTE: There might be no recorded root when this function is called. | ||
| * NOTE2: There might be no recorded root when this function is called. | ||
| */ | ||
| asyncPromisifyPromiseId; | ||
| } |
| import StaticDataNode from './StaticDataNode'; | ||
| /** @typedef {import('../Loc').default} Loc */ | ||
| /** @typedef {import('./Loc').default} Loc */ | ||
@@ -5,0 +5,0 @@ |
+50
-1
@@ -0,1 +1,4 @@ | ||
| /** @typedef { import("./constants/SpecialIdentifierType").default } SpecialIdentifierType */ | ||
| /** @typedef { import("./constants/SpecialDynamicTraceType").default } SpecialDynamicTraceType */ | ||
| export class TracePurposeInfo { | ||
@@ -7,3 +10,49 @@ type; | ||
| export class TraceData { | ||
| /** | ||
| * only: BCE. | ||
| * traceId of the callee. | ||
| */ | ||
| calleeTid; | ||
| /** | ||
| * only: BCE. | ||
| * @type {number[]} | ||
| */ | ||
| argTids; | ||
| /** | ||
| * only: BCE. | ||
| */ | ||
| spreadLengths; | ||
| /** | ||
| * only: BCE. | ||
| * Assigned in case of `call`, `apply`, `bind` etc. | ||
| */ | ||
| calledFunctionTid; | ||
| /** | ||
| * only: BCE. | ||
| * | ||
| * Contains custom data generated by monkey-patched built-ins. | ||
| */ | ||
| monkey; | ||
| /** | ||
| * Statically determined special properties of a trace. | ||
| * | ||
| * {@link SpecialIdentifierType} | ||
| */ | ||
| specialType; | ||
| /** | ||
| * Dynamically determined special properties of a trace. | ||
| * | ||
| * {@link SpecialTraceDynamicType} | ||
| */ | ||
| specialDynamicType; | ||
| } | ||
| export default class Trace { | ||
@@ -71,5 +120,5 @@ /** | ||
| * Extra data related to this trace, based on circumstances. | ||
| * -> contains { argTids, spreadLengths[, monkey] } for BCE. | ||
| * @type {TraceData} | ||
| */ | ||
| data; | ||
| } |
| /* eslint no-console: 0 */ | ||
| import isString from 'lodash/isString'; | ||
@@ -7,6 +6,7 @@ /** | ||
| */ | ||
| import colors from 'colors/safe'; | ||
| import { err2String } from './errorLog'; | ||
| // const inspectOptions = { depth: 0, colors: true }; | ||
@@ -28,3 +28,3 @@ // function _inspect(arg) { | ||
| ...args.map( | ||
| arg => (arg && (arg.constructor === String || arg instanceof Error)) ? | ||
| arg => (arg && (arg.constructor === String || arg instanceof Error)) ? | ||
| colorize(err2String(arg)) : | ||
@@ -35,3 +35,3 @@ // _inspect(arg) | ||
| ); | ||
| }; | ||
| }; | ||
| } | ||
@@ -49,37 +49,1 @@ | ||
| console.debug = makePrettyLog(console.debug, 'gray'); | ||
| /** ########################################################################### | ||
| * util | ||
| * ##########################################################################*/ | ||
| // eslint-disable-next-line no-inner-declarations | ||
| function err2String(err) { | ||
| if (Array.isArray(err?.stack)) { | ||
| /** | ||
| * stack is array of `CallSite` | ||
| */ | ||
| return `${err.message}\n ${err.stack.map(callSite2String).join('\n ')}`; | ||
| } | ||
| return isString(err?.stack) && err.stack.includes(err.message) ? err.stack : err.toString(); | ||
| } | ||
| /** | ||
| * @see https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_globals_d_.nodejs.callsite.html | ||
| * @see https://github.com/dougwilson/nodejs-depd/blob/master/index.js#L267 | ||
| */ | ||
| function callSite2String(callSite) { | ||
| let file = callSite.getFileName() || '<anonymous>'; | ||
| const line = callSite.getLineNumber(); | ||
| const col = callSite.getColumnNumber(); | ||
| if (callSite.isEval()) { | ||
| file = callSite.getEvalOrigin() + ', ' + file; | ||
| } | ||
| // site.callSite = callSite; | ||
| const fname = callSite.getFunctionName(); | ||
| return `at ${fname} (${file}:${line}:${col})`; | ||
| } |
+32
-18
| import { newLogger } from '../log/logger'; | ||
| // eslint-disable-next-line no-unused-vars | ||
| const { log, debug, warn, error: logError } = newLogger('makeDebounce'); | ||
| const { log, debug, warn, error: logError } = newLogger('throttle'); | ||
| /** | ||
| * Make sure, function is not called more than once every `ms` milliseconds. | ||
| * Makes sure, function is not called more than once every `ms` milliseconds. | ||
| * NOTE: lodash/throttle does not work with async functions. | ||
| * @see https://github.com/Domiii/dbux/blob/master/dbux-common/src/util/scheduling.js | ||
| * @see https://github.com/lodash/lodash/issues/4815 | ||
| */ | ||
| // eslint-disable-next-line camelcase | ||
| export function makeDebounce(cb, ms = 300) { | ||
| let timer; | ||
| function _wrapDebounce() { | ||
| timer = null; | ||
| try { | ||
| cb(); | ||
| export function throttle(cb, ms = 300) { | ||
| let p, args; | ||
| return (..._args) => { | ||
| args = _args; // take the latest arguments | ||
| if (!p) { | ||
| p = new Promise((resolve, reject) => { | ||
| setTimeout(async function _wrappedCb() { | ||
| // allow throttle to be scheduled again at this point | ||
| p = null; | ||
| // start doing the work | ||
| try { | ||
| const result = await cb(...args); | ||
| resolve(result); | ||
| } | ||
| catch (err) { | ||
| // logError('Error when executing callback', cb.name?.trim() || '(anonymous callback)', '-', err); | ||
| reject(err); | ||
| } | ||
| finally { | ||
| resolve = null; | ||
| reject = null; | ||
| } | ||
| }, ms); | ||
| }); | ||
| } | ||
| catch (err) { | ||
| logError('Error when executing callback', | ||
| cb.name?.trim() || '(anonymous callback)', '-', err); | ||
| } | ||
| } | ||
| return () => { | ||
| if (!timer) { | ||
| timer = setTimeout(_wrapDebounce, ms); | ||
| } | ||
| return p; | ||
| }; | ||
| } |
@@ -19,4 +19,4 @@ import truncate from 'lodash/truncate'; | ||
| */ | ||
| export function makeShortString(s, cfg = ShortenCfg) { | ||
| export function truncateStringDefault(s, cfg = ShortenCfg) { | ||
| return truncate(s.replace(/\s+/g, ' '), cfg); | ||
| } |
@@ -48,16 +48,22 @@ /** | ||
| */ | ||
| let _r; | ||
| let __r; | ||
| export function _require(name) { | ||
| if (_r !== undefined) { | ||
| return _r; | ||
| } | ||
| // eslint-disable-next-line no-eval | ||
| _r = eval(` | ||
| const _r = __r || (__r = eval(` | ||
| ((typeof __non_webpack_require__ !== 'undefined' && __non_webpack_require__) || | ||
| (typeof require !== 'undefined' && require)) | ||
| `) || null; | ||
| `)) || null; | ||
| if (!_r) { | ||
| return null; | ||
| } | ||
| return _r(name); | ||
| let m = _r(name); | ||
| const Module = _r('module'); | ||
| if (m instanceof Module) { | ||
| /** | ||
| * Require might return a module object, rather than its exported content in an ESM context. | ||
| * @see https://nodejs.org/api/module.html#the-module-object | ||
| */ | ||
| m = m.default; | ||
| } | ||
| return m; | ||
| } | ||
@@ -78,3 +84,8 @@ | ||
| /** | ||
| * | ||
| */ | ||
| export const crypto = universalLib(null, 'crypto'); | ||
| // NOTE: inspect does not exist in the browser | ||
@@ -81,0 +92,0 @@ // /** |
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
106225
5.24%79
3.95%3137
6.09%Updated