@squaredup/plugin-common
Advanced tools
| { | ||
| "recommendations": [ | ||
| "dbaeumer.vscode-eslint", | ||
| "esbenp.prettier-vscode", | ||
| "streetsidesoftware.code-spell-checker", | ||
| "vitest.explorer" | ||
| ], | ||
| } |
+124
-7
@@ -0,1 +1,2 @@ | ||
| import { createHash, randomBytes } from 'crypto'; | ||
| import { isErrorLike, serializeError } from 'serialize-error'; | ||
@@ -146,8 +147,9 @@ | ||
| const errorName = error.name || error.response?.statusText; | ||
| const errorObject = { errorMessage: error.message, errorName, stack: error.stack }; // Tells us what and where | ||
| // If enabled we'll log straight to the error log, if not we'll throw them in debug for troubleshooting. | ||
| if (options.logAllErrors) { | ||
| log.error(`${errorName}: ${errorString}`); | ||
| log.error(`${errorName}: ${errorString}`, errorObject); | ||
| } else { | ||
| log.debug(`${errorName}: ${errorString}`); | ||
| log.debug(`${errorName}: ${errorString}`, errorObject); | ||
| } | ||
@@ -405,3 +407,3 @@ | ||
| if (!log) { | ||
| throw new error('No log object passed to isValidEdge. Ensure you have passed a valid context object.'); | ||
| throw new Error('No log object passed to isValidVertex. Ensure you have passed a valid context object.'); | ||
| } | ||
@@ -442,3 +444,3 @@ | ||
| if (!log) { | ||
| throw new error('No log object passed to isValidEdge. Ensure you have passed a valid context object.'); | ||
| throw new Error('No log object passed to isValidEdge. Ensure you have passed a valid context object.'); | ||
| } | ||
@@ -519,3 +521,3 @@ | ||
| * Generates a function that automatically tracks warnings reported to the user | ||
| * | ||
| * | ||
| * @param { Object } context A standard context object. | ||
@@ -527,3 +529,3 @@ * @returns A function for deduplicating warnings | ||
| if(!log || !report) { | ||
| if (!log || !report) { | ||
| throw new Error('Ensure you have passed a valid context object'); | ||
@@ -535,3 +537,3 @@ } | ||
| /** | ||
| * Takes a message and optionally another object. | ||
| * Takes a message and optionally another object. | ||
| * Reports a warning if it has not already been reported, debug logs it otherwise | ||
@@ -549,1 +551,116 @@ */ | ||
| }; | ||
| /** | ||
| * Generates a PKCE verifier and challenge. | ||
| * The challenge is the verifier string encrypted using SHA256. We send the | ||
| * challenge with the first call and the verifier with the second call. | ||
| * This verifies that we are the correct party when redeeming. | ||
| * | ||
| * @returns An object containing a verifier, and a challenge. | ||
| */ | ||
| export const generatePkcePair = () => { | ||
| // Generate a 50 char string, where 1 byte is 2 chars. | ||
| // We need between 43 and 128 chars to be valid. | ||
| const verifier = randomBytes(25).toString('hex'); | ||
| const hash = createHash('sha256').update(verifier).digest('base64'); | ||
| // Make the challenge safe for URL encoding. | ||
| const challenge = hash.replace(/\+/gu, '-').replace(/\//gu, '_').replace(/=+$/u, ''); | ||
| return { verifier, challenge }; | ||
| }; | ||
| /** | ||
| * Generates a standard axios request logInterceptor. | ||
| * Spread into axios.interceptors.request.use. | ||
| * | ||
| * @param {*} context A standard context object with log and report objects | ||
| * @example axios.interceptors.request.use(...generateAxiosRequestLogInterceptors(context)); | ||
| * @returns An array of configuration | ||
| */ | ||
| export const generateAxiosRequestLogInterceptors = ({ log, report }) => { | ||
| if (!log || !report) { | ||
| throw new Error('Ensure you have passed a valid context/api object'); | ||
| } | ||
| return [ | ||
| (config) => { | ||
| const { baseURL, body, data, method, url, params } = config; | ||
| log.debug(`Sending request to ${url}`, { baseURL, body: body ?? data, method, params, url }); | ||
| return config; | ||
| }, | ||
| (error) => { | ||
| const { config, message, stack } = error; | ||
| // Error logging can happen later if it is warranted. | ||
| log.debug(`Error setting up request to ${config?.url}`, { message, stack }); | ||
| return Promise.reject(error); | ||
| }, | ||
| { synchronous: true } | ||
| ]; | ||
| }; | ||
| /** | ||
| * Generates a standard axios response logInterceptor. | ||
| * Spread into axios.interceptors.response.use. | ||
| * | ||
| * @param {*} context A standard context object with log and report objects | ||
| * @example axios.interceptors.response.use(...generateAxiosResponeLogInterceptors(context)); | ||
| * @returns An array of configuration | ||
| */ | ||
| export const generateAxiosResponeLogInterceptors = ({ log, report }) => { | ||
| if (!log || !report) { | ||
| throw new Error('Ensure you have passed a valid context object'); | ||
| } | ||
| return [ | ||
| (response) => { | ||
| const { config, status, statusText } = response; | ||
| log.debug(`Successful response from ${config.url}`, { status, statusText }); | ||
| return response; | ||
| }, | ||
| (error) => { | ||
| const { response, request, config, code, message, stack } = error; | ||
| const configuration = { | ||
| body: config?.body ?? config?.data, | ||
| params: config?.params, | ||
| method: config?.method, | ||
| url: config?.url | ||
| }; | ||
| const errorObject = { code, message, stack }; | ||
| // Error logging can happen later if it is warranted. | ||
| if (response) { | ||
| const { data, status, headers, statusText } = response; | ||
| log.debug(`Error response from ${configuration.url}`, { | ||
| configuration, | ||
| data, | ||
| error: errorObject, | ||
| path: request?.path, | ||
| status, | ||
| statusText, | ||
| retryAfter: headers.get('Retry-After') | ||
| }); | ||
| } else if (request) { | ||
| log.debug(`Error making request to ${configuration.url}`, { | ||
| configuration, | ||
| error: errorObject, | ||
| path: request.path | ||
| }); | ||
| } else { | ||
| log.debug(`Error configuring request to ${configuration.url}`, { configuration, error: errorObject }); | ||
| } | ||
| return Promise.reject(error); | ||
| }, | ||
| { synchronous: true } | ||
| ]; | ||
| }; |
+7
-2
| { | ||
| "name": "@squaredup/plugin-common", | ||
| "version": "2.1.0", | ||
| "version": "2.2.0", | ||
| "description": "Common functions that can be used by any plugin", | ||
@@ -10,3 +10,4 @@ "type": "module", | ||
| "test": "vitest --reporter=verbose --reporter=junit --outputFile.junit=tests_output/junit.xml", | ||
| "fast": "pnpm i --frozen-lockfile" | ||
| "fast": "pnpm i --frozen-lockfile", | ||
| "lint": "eslint ." | ||
| }, | ||
@@ -16,4 +17,8 @@ "author": "SquaredUp", | ||
| "devDependencies": { | ||
| "@babel/core": "^7.28.5", | ||
| "@babel/eslint-parser": "^7.28.5", | ||
| "@types/node": "18", | ||
| "eslint": "^8.57.0", | ||
| "eslint-config-prettier": "^9.1.0", | ||
| "eslint-plugin-no-only-tests": "^3.3.0", | ||
| "prettier": "^3.2.5", | ||
@@ -20,0 +25,0 @@ "prettier-plugin-organize-imports": "^3.2.4", |
+5
-0
@@ -20,1 +20,6 @@ # Plugin-Common | ||
| - `warningTracker` : a helper function that generates functions that can be used to track warnings sent to users | ||
| - `generatePkcePair` : a helper function that generates a challenge code and verifier for use with PKCE | ||
| - `generateAxiosRequestLogInterceptors` : a helper function that generates interceptors for axios that log requests consistently | ||
| - note that this does not prevent you from adding more interceptors to do something less generic later. | ||
| - `generateAxiosResponeLogInterceptors` : a helper function that generates interceptors for axios that log responses consistently | ||
| - note that this does not prevent you from adding more interceptors to do something less generic later. |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
27790
22.62%5
25%586
22.08%25
25%9
80%6
100%