@alttiri/util-node-js
Advanced tools
Comparing version 1.6.0 to 2.0.0
32
index.js
@@ -1,26 +0,6 @@ | ||
export { | ||
saveCursorPosition, | ||
restoreCursorPosition, | ||
eraseCursorLine, | ||
moveCursorToTop | ||
} from "./src/console.js"; | ||
export { | ||
getColoring, | ||
getAnsiColoring, | ||
ANSI_BLUE, | ||
ANSI_CYAN, | ||
ANSI_GREEN, | ||
ANSI_GRAY, | ||
ANSI_GREEN_BOLD, | ||
ANSI_RED_BOLD, | ||
COL_ORANGE, | ||
COL_VIOLET, | ||
COL_GRAY, | ||
} from "./src/console.js"; | ||
export { | ||
Tester | ||
} from "./src/tester.js"; | ||
export * from "./src/console.js"; | ||
export * from "./src/console-colors.js"; | ||
export * from "./src/filesystem.js"; | ||
export * from "./src/fs-list/filesystem-listing.js"; | ||
export * from "./src/tester.js"; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@alttiri/util-node-js", | ||
"version": "1.6.0", | ||
"description": "Some Node.js util functions", | ||
"version": "2.0.0", | ||
"description": "Some Node.js util functions for personal use", | ||
"keywords": [ | ||
"color" | ||
"color", | ||
"readdir", | ||
"tester" | ||
], | ||
@@ -12,6 +14,10 @@ "homepage": "https://github.com/alttiri/util-node-js", | ||
"files": [ | ||
"src", | ||
"index.js" | ||
"src/**/*.js", | ||
"src/**/*.js.map", | ||
"src/**/*.d.ts", | ||
"index.js", | ||
"index.js.map", | ||
"index.d.ts" | ||
], | ||
"main": "index.js", | ||
"main": "./index.js", | ||
"repository": { | ||
@@ -24,11 +30,22 @@ "type": "git", | ||
}, | ||
"devDependencies": { | ||
"@types/node": "18.16.18", | ||
"typescript": "5.1.6" | ||
}, | ||
"scripts": { | ||
"compile": "tsc --build", | ||
"compile-watch": "tsc --build --watch", | ||
"clean": "tsc --build --clean", | ||
"-": "", | ||
"publish-npm": "npm publish --registry=https://registry.npmjs.org", | ||
"publish-ghp": "npm publish --registry=https://npm.pkg.github.com", | ||
"#": "", | ||
"--": "", | ||
"unpublish-npm": "npm unpublish @alttiri/util-node-js@1.2.3 --registry=https://registry.npmjs.org", | ||
"##": "", | ||
"---": "", | ||
"login-npm": "npm login --registry=https://registry.npmjs.org", | ||
"login-ghp": "npm login --registry=https://npm.pkg.github.com" | ||
}, | ||
"dependencies": { | ||
"@alttiri/util-js": "1.9.0" | ||
} | ||
} |
# util-node-js | ||
Some Node.js util functions. | ||
Mostly it's a draft version for personal use. | ||
## Installation | ||
@@ -11,43 +15,9 @@ | ||
### From GitHub repository | ||
```bash | ||
npm install git+https://github.com/alttiri/util-node-js.git | ||
``` | ||
<details> | ||
<summary>More ways</summary> | ||
<summary>From GitHub Packages</summary> | ||
### From GitHub repository (a specific version): | ||
- **Based on SemVer:** | ||
```bash | ||
npm install git+https://github.com/alttiri/util-node-js.git#semver:1.6.0 | ||
``` | ||
Or add | ||
``` | ||
"@alttiri/util-node-js": "github:alttiri/util-node-js#semver:1.6.0" | ||
``` | ||
as `dependencies` in `package.json` file. | ||
See available [tags](https://github.com/AlttiRi/util-node-js/tags). | ||
- **Based on a commit hash:** | ||
```bash | ||
npm install git+https://git@github.com/alttiri/util-node-js.git#c98d3919e9002fa5738680a2c76004fd12746ce3 | ||
``` | ||
Or add | ||
``` | ||
"@alttiri/util-node-js": "github:alttiri/util-node-js#c98d3919e9002fa5738680a2c76004fd12746ce3" | ||
``` | ||
as `dependencies` in `package.json` file. | ||
See available [commits hashes](https://github.com/AlttiRi/util-node-js/commits/master). | ||
### From GitHub Packages: | ||
To install you need fisrt to create `.npmrc` file with `@alttiri:registry=https://npm.pkg.github.com` content: | ||
To install you need first to create `.npmrc` file with `@alttiri:registry=https://npm.pkg.github.com` content: | ||
```bash | ||
@@ -64,6 +34,2 @@ echo @alttiri:registry=https://npm.pkg.github.com >> .npmrc | ||
</details> | ||
const _ANSI_RESET = "\u001B[0m"; | ||
/** @typedef {"black"|"red"|"green"|"yellow"|"blue"|"magenta"|"cyan"|"white"} ANSIColor */ | ||
/** @type {Map<ANSIColor, number>} */ | ||
const ansiColorsMap = new Map([ | ||
["black", 30], | ||
["red", 31], | ||
["green", 32], | ||
["yellow", 33], | ||
["blue", 34], | ||
["black", 30], | ||
["red", 31], | ||
["green", 32], | ||
["yellow", 33], | ||
["blue", 34], | ||
["magenta", 35], | ||
["cyan", 36], | ||
["white", 37], | ||
["cyan", 36], | ||
["white", 37], | ||
]); | ||
/** | ||
@@ -29,9 +24,9 @@ * [ANSI_escape_code#SGR]{@link https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters} | ||
* console.log(COL_VIOLET_DARK("This text is 8-bit dark violet")); | ||
* @param {String} mode | ||
* @return {function(text: any): String} | ||
* | ||
* @param {string} mode | ||
* @return {ColoringFunc} | ||
*/ | ||
export function getColoring(mode) { | ||
return text => `\u001B[${mode}m${text}${_ANSI_RESET}`; | ||
return (text) => `\u001B[${mode}m${text}${_ANSI_RESET}`; | ||
} | ||
/** | ||
@@ -41,10 +36,10 @@ * @example | ||
* console.log(ANSI_RED_BOLD("This text is bold red")); | ||
* @param {ANSIColor} [color="white"] | ||
* @param {Object} [opts] | ||
* @param {Boolean} [opts.bright=false] | ||
* @param {Boolean} [opts.bold=false] | ||
* @return {function(text: any): String} | ||
* @param {ANSIColor?} color = "white" | ||
* @param {AnsiColoringOpts?} opts | ||
* @param {boolean?} opts.bright = false | ||
* @param {boolean?} opts.bold = false | ||
* @return {ColoringFunc} | ||
*/ | ||
export function getAnsiColoring(color = "white", opts= {}) { | ||
const {bright, bold} = Object.assign({bright: false, bold: false}, opts); | ||
export function getAnsiColoring(color = "white", opts = {}) { | ||
const { bright = false, bold = false } = opts; | ||
let num = ansiColorsMap.get(color); | ||
@@ -58,1 +53,2 @@ if (bright) { | ||
} | ||
//# sourceMappingURL=console-colors-core.js.map |
@@ -1,18 +0,13 @@ | ||
import {getColoring, getAnsiColoring} from "./console-colors-core.js"; | ||
export { | ||
getColoring, | ||
getAnsiColoring, | ||
}; | ||
import { getColoring, getAnsiColoring } from "./console-colors-core.js"; | ||
export { getColoring, getAnsiColoring, }; | ||
// Some predefined colors | ||
export const ANSI_BLUE = /*#__PURE__*/ getAnsiColoring("blue"); | ||
export const ANSI_CYAN = /*#__PURE__*/ getAnsiColoring("cyan"); | ||
export const ANSI_BLUE = /*#__PURE__*/ getAnsiColoring("blue"); | ||
export const ANSI_CYAN = /*#__PURE__*/ getAnsiColoring("cyan"); | ||
export const ANSI_GREEN = /*#__PURE__*/ getAnsiColoring("green"); | ||
export const ANSI_GRAY = /*#__PURE__*/ getAnsiColoring("black", {bright: true}); | ||
export const ANSI_GREEN_BOLD = /*#__PURE__*/ getAnsiColoring("green", {bold: true}); | ||
export const ANSI_RED_BOLD = /*#__PURE__*/ getAnsiColoring("red", {bold: true}); | ||
export const ANSI_GRAY = /*#__PURE__*/ getAnsiColoring("black", { bright: true }); | ||
export const ANSI_GREEN_BOLD = /*#__PURE__*/ getAnsiColoring("green", { bold: true }); | ||
export const ANSI_RED_BOLD = /*#__PURE__*/ getAnsiColoring("red", { bold: true }); | ||
export const COL_ORANGE = /*#__PURE__*/ getColoring("38;5;208"); | ||
export const COL_VIOLET = /*#__PURE__*/ getColoring("38;5;99"); | ||
export const COL_GRAY = /*#__PURE__*/ getColoring("38;5;245"); | ||
export const COL_GRAY = /*#__PURE__*/ getColoring("38;5;245"); | ||
//# sourceMappingURL=console-colors.js.map |
export * from "./console-colors.js"; | ||
export const saveCursorPosition = () => process.stdout.write("\u001B[s"); | ||
export const saveCursorPosition = () => process.stdout.write("\u001B[s"); | ||
export const restoreCursorPosition = () => process.stdout.write("\u001B[u"); | ||
export const eraseCursorLine = () => process.stdout.write("\u001B[K"); | ||
export const eraseCursorLine = () => process.stdout.write("\u001B[K"); | ||
export const moveCursorToTop = (num = 1) => process.stdout.write(`\u001B[${num}A`); | ||
//# sourceMappingURL=console.js.map |
@@ -1,16 +0,7 @@ | ||
import fs from "fs/promises"; | ||
import path from "path"; | ||
import fs from "node:fs/promises"; | ||
import path from "node:path"; | ||
export function exists(path, followSymbol = true) { | ||
return (followSymbol ? fs.stat(path) : fs.lstat(path)) | ||
.then(stats => true) | ||
.catch(error => false); | ||
return (followSymbol ? fs.stat(path) : fs.lstat(path)).then(() => true, () => false); | ||
} | ||
/** | ||
* Is the passed symlink looped — if referrers to a parent directory. | ||
* @param {string} filepath | ||
* @return {Promise<boolean>} | ||
*/ | ||
/** Is the passed symlink looped — if referrers to a parent directory. */ | ||
export async function isSymLooped(filepath) { | ||
@@ -20,5 +11,31 @@ const filepathAbsolute = path.resolve(filepath); | ||
const linkPath = await fs.readlink(filepathAbsolute); | ||
const linkPathAbsolute = path.resolve(dirname, linkPath); // since `linkPath` can be ".", for example | ||
const linkPathAbsolute = path.resolve(dirname, linkPath); // Since `linkPath` can be ".", for example. | ||
return linkPathAbsolute.includes(dirname); | ||
} | ||
export async function getFileInfo(filepath) { | ||
filepath = path.resolve(filepath); | ||
const stats = await fs.lstat(filepath); | ||
if (stats.isSymbolicLink()) { | ||
return { | ||
path: filepath, | ||
stats, | ||
link: await readLink(filepath), | ||
}; | ||
} | ||
else { | ||
return { | ||
path: filepath, | ||
stats, | ||
}; | ||
} | ||
} | ||
export async function readLink(filepath) { | ||
const symContent = await fs.readlink(filepath); | ||
const linkLocation = path.dirname(filepath); | ||
const absolutePathTo = path.resolve(linkLocation, symContent); | ||
return { | ||
pathTo: absolutePathTo, | ||
content: symContent, | ||
}; | ||
} | ||
//# sourceMappingURL=filesystem.js.map |
@@ -1,19 +0,9 @@ | ||
import {ANSI_GRAY, ANSI_GREEN, ANSI_RED_BOLD} from "./console-colors.js"; | ||
/** | ||
* A pretty simple tester. | ||
* @example | ||
* const {eq, report} = new Tester().destructible(); | ||
* | ||
* eq("ab0", Math.max(1, 2), 2); | ||
* eq("ab1", " qwe ".trim(), "qwe"); | ||
* | ||
* report(); | ||
*/ | ||
import { ANSI_BLUE, ANSI_GRAY, ANSI_GREEN_BOLD, ANSI_RED_BOLD } from "./console-colors.js"; | ||
export class Tester { | ||
constructor(printSuccess = true) { | ||
this.passed = []; | ||
this.failed = []; | ||
this.printSuccess = printSuccess; | ||
this.num = 0; | ||
/** @deprecated */ | ||
eq(name, result, expect) { | ||
return this.t({ | ||
result, expect, name, | ||
autoReport: false, stackDeep: 1, printSuccess: true, | ||
}); | ||
} | ||
@@ -23,41 +13,74 @@ destructible() { | ||
eq: this.eq.bind(this), | ||
t: this.t.bind(this), | ||
report: this.report.bind(this), | ||
} | ||
}; | ||
} | ||
eq(name, result, expected) { | ||
constructor(opt) { | ||
const { printSuccess = false, testOnly = [], stackDeep = 0, autoReport = true, } = opt || {}; | ||
this.passed = []; | ||
this.failed = []; | ||
this.printSuccess = printSuccess; | ||
this.num = 0; | ||
this.testOnly = testOnly; | ||
this.stackDeep = stackDeep; | ||
this.timerId = -1; | ||
this.autoReport = autoReport; | ||
} | ||
t(opt) { | ||
const { result, expect, stackDeep, name = "", printLink = true, autoReport = this.autoReport, printSuccess = this.printSuccess, } = opt; | ||
const { filename, lineNum } = getLineNum(2 + (stackDeep ?? this.stackDeep)); | ||
this.num++; | ||
const errorLines = new Error().stack.split("\n"); | ||
if (errorLines[0] === "Error") { | ||
errorLines.shift(); | ||
if (this.testOnly.length && !this.testOnly.includes(this.num)) { | ||
return; | ||
} | ||
const match = errorLines[1]?.match(/\d+(?=:\d+$)/); | ||
const lineNum = match?.[0] || ""; | ||
const prefix = `[${this.num.toString().padStart(3)}][${lineNum.padStart(4)}]`; | ||
const quotes = result.toString().match(/^\s|\s$/) || expected.toString().match(/^\s|\s$/); | ||
const q1 = quotes ? ANSI_GRAY("\"") : " "; | ||
const q2 = quotes ? ANSI_GRAY("\"") : ""; | ||
const colon = ANSI_GRAY(":"); | ||
if (result === expected) { | ||
this.passed.push(name); | ||
if (!this.printSuccess) { | ||
return; | ||
const pad1 = " ".repeat(2 - this.num.toString().length); | ||
const pad2 = " ".repeat(3 - lineNum.toString().length); | ||
if (expect === undefined) { | ||
console.log(ANSI_BLUE(this.num), pad1, ANSI_GRAY(lineNum), pad2, result, name); | ||
} | ||
else { | ||
const eq = result === expect; | ||
if (eq) { | ||
console.log(ANSI_GREEN_BOLD(this.num), pad1, ANSI_GRAY(lineNum), pad2, ANSI_GREEN_BOLD("passed"), name); | ||
printSuccess && console.log(ANSI_GRAY("result: "), ANSI_BLUE(result)); | ||
printSuccess && console.log(ANSI_GRAY("---")); | ||
this.passed.push(this.num); | ||
} | ||
console.log(ANSI_GREEN(`${prefix} Test ${name} passed`)); | ||
console.log(`Expected ${colon} ${q1}${result}${q2}`); | ||
console.log(`Result ${colon} ${q1}${result}${q2}`); | ||
console.log(ANSI_GRAY("---")); | ||
} else { | ||
this.failed.push(name); | ||
console.log(ANSI_RED_BOLD(`${prefix} Test ${name} failed`)); | ||
console.log(`Expected ${colon} ${q1}${expected}${q2}`); | ||
console.log(`Result ${colon} ${q1}${result}${q2}`); | ||
console.log(ANSI_GRAY("---")); | ||
else { | ||
console.log(ANSI_RED_BOLD(this.num), pad1, ANSI_GRAY(lineNum), pad2, ANSI_RED_BOLD("failed"), name); | ||
console.log(ANSI_GRAY("expect: "), ANSI_BLUE(expect)); | ||
console.log(ANSI_GRAY("result: "), ANSI_RED_BOLD(result)); | ||
printLink && console.log(`file:///./${filename}:${lineNum}`); // Expects work dir === file location | ||
this.failed.push(this.num); | ||
console.log(ANSI_GRAY("---")); | ||
} | ||
} | ||
autoReport && this.delayReport(); | ||
} | ||
delayReport() { | ||
clearTimeout(this.timerId); | ||
this.timerId = setTimeout(() => this.report(), 50); | ||
} | ||
report() { | ||
console.log(); | ||
const c = this.failed.length ? ANSI_RED_BOLD : ANSI_GRAY; | ||
console.log(c(`Failed: ${this.failed.length.toString().padStart(3)}`)); | ||
console.log( `Passed: ${this.passed.length.toString().padStart(3)}`); | ||
console.log(ANSI_GRAY("---------------")); | ||
const COLOR_PASS = this.passed.length ? ANSI_GREEN_BOLD : ANSI_GRAY; | ||
const COLOR_FAIL = this.failed.length ? ANSI_RED_BOLD : ANSI_GRAY; | ||
console.log(COLOR_PASS(this.passed.length.toString().padStart(8) + " passed")); | ||
console.log(COLOR_FAIL(this.failed.length.toString().padStart(8) + " failed")); | ||
console.log(ANSI_GRAY("---------------\n")); | ||
} | ||
} | ||
/** | ||
* @param {number} stackDeep | ||
* @return {{filename?: string, line?: string, column?: string}} | ||
*/ | ||
function getLineNum(stackDeep = 2) { | ||
const errorLines = new Error().stack.split("\n"); | ||
if (errorLines[0] === "Error") { | ||
errorLines.shift(); | ||
} | ||
const fileLine = errorLines[stackDeep]?.split("/").pop(); | ||
const { filename, line, column } = fileLine?.match(/(?<filename>.+):(?<line>\d+):(?<column>\d+)/)?.groups || {}; | ||
return { filename, lineNum: line, column }; | ||
} | ||
//# sourceMappingURL=tester.js.map |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
47946
36
795
0
1
2
34
1
+ Added@alttiri/util-js@1.9.0
+ Added@alttiri/util-js@1.9.0(transitive)