
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
Functional toolkit for file/dir paths. Drop-in path replacement.
Originally built for a static site generator where path transformations are common, but use-cases
are really unlimited.
Peer dependencies:
@paqmind/ramdax (temp. until basic Ramda)Dependencies:
path (Server)path-webpack (Browser)$ npm install pathz
let P = require("pathz") // defaults to either POSIX or WIN32
let P_posix = require("pathz/posix") // POSIX (P.sep is / etc.)
let P_win32 = require("pathz/win32") // WIN32 (P.sep is \ etc.)
// The following snippets also use shortcuts for:
let R = require("ramdax")
let PP = require("path")
Usage hint. Webpack's path-browserify dependency (polyfill of path) is very old and severily broken.
It doesn't even provide a parse function! If you want to import path directly, be sure to
substitute it with another package. Add the following to your webpack.config.js:
resolve: {
alias: {
path: "path-webpack"
}
}
This can fix other libraries naively depending on path btw. Other bundlers, like Browserify
or Rollup, should support such replacement. You can use this approach to keep import P from "path"
or import P from pathz/lib/browser instead. There's no support for Win-32 separators in Browser a.t.m.
format / parse provide limited, low-level, mutable APIpathz respects trailing separators as possible directory indicatorconsole.log(PP.dirname("/foo/bar/")) // "/foo"
console.log(P.dir("/foo/bar/")) // "/foo/bar/"
console.log(PP.basename("/foo/bar/")) // "bar"
console.log(P.base("/foo/bar/")) // ""
pathz respects "relativeness" and "absoluteness" of pathsconsole.log(P.addLeftDir("bar", "/foo.txt")) // "/bar/foo.txt" (+)
console.log(PP.join("bar", "/foo.txt")) // "bar/foo.txt" (-) naive
console.log(P.addRightDir("bar", "/foo.txt")) // "/bar/foo.txt" (+)
console.log(PP.join("/foo.txt", "bar")) // "/foo.txt/bar" (-) naive
pathz is composition friendlylet R = require("ramdax")
let src = "content/team/about.md"
let dst = R.pipe(
P.withLeftDir("public"),
P.addRightDir(P.name(src)),
P.withBase("index.html")
)(src)
console.log(dst) // "public/team/about/index.html"
// corresponding to "/team/about/" URL
pathz is like CRUD for path fragments// GET
console.log(P.leftDir("/foo/bar/baz.txt")) // "foo"
console.log(P.rightDir("/foo/bar/baz.txt")) // "bar"
// UPDATE
console.log(P.withLeftDir ("qux", "/foo/bar/baz.txt")) // "/qux/bar/baz.txt"
console.log(P.withRightDir("qux", "/foo/bar/baz.txt")) // "/foo/qux/baz.txt"
// DELETE
console.log(P.dropLeftDir ("/foo/bar/baz.txt")) // "/bar/baz.txt"
console.log(P.dropRightDir("/foo/bar/baz.txt")) // "/foo/baz.txt"
// ...
pathz provides extra utilsR.sortBy(P.padPath(2))([
"foo/bar/11.1/2.1",
"foo/bar/2.1/10.1",
"foo/bar/10.1/2.1",
"foo/bar/2.1/2.1",
])
// [ 'foo/bar/2.1/2.1',
// 'foo/bar/2.1/10.1',
// 'foo/bar/10.1/2.1',
// 'foo/bar/11.1/2.1' ]
dir :: String -> StringP.dir("foo/bar/baz.txt") // "foo/bar/" (P.dirname + "/")
P.dir("foo/bar/") // "foo/bar/" (identity)
P.dir("/foo/bar/baz.txt") // "/foo/bar/" (P.dirname + "/")
P.dir("/foo/bar/") // "/foo/bar/" (identity)
splitDirs :: String -> [String]P.splitDirs("foo/bar/baz.txt") // ["foo", "bar"]
P.splitDirs("/foo/bar/") // ["foo", "bar"]
base :: String -> StringP.base("foo/bar/baz.txt") // "baz.txt" (P.basename)
P.base("foo/bar/") // "" (zero)
name :: String -> StringP.name("whatever/index.html") // "index"
P.name("whatever/.gitignore") // ".gitignore"
ext :: String -> StringP.ext("whatever/index.html") // ".html"
P.ext("whatever/.gitignore") // ""
leftDir :: String -> StringP.leftDir("foo/bar/index.html") // "foo"
P.leftDir("foo") // ""
P.leftDir("foo/") // "foo"
rightDir :: String -> StringP.rightDir("foo/bar/index.html") // "bar"
P.rightDir("foo") // ""
P.rightDir("foo/") // "foo"
leftDirs :: Number -> String -> StringP.leftDirs(1) == P.leftDir
P.leftDirs(2, "foo/bar/baz/qux.txt") // "foo/bar"
P.leftDirs(3, "foo/bar/baz/qux.txt") // "foo/bar/baz"
P.leftDirs(4, "/foo/bar/baz/qux.txt") // "foo/bar/baz"
rightDirs :: Number -> String -> StringP.rightDirs(1) == P.rightDir
P.rightDirs(2, "foo/bar/baz/qux.txt") // "bar/baz"
P.rightDirs(3, "foo/bar/baz/qux.txt") // "foo/bar/baz"
P.rightDirs(4, "/foo/bar/baz/qux.txt") // "foo/bar/baz"
addLeftDir :: String -> String -> StringP.addLeftDir("foo", "bar/index.html") // "foo/bar/index.html"
P.addLeftDir("foo", "") // "foo/"
addRightDir :: String -> String -> StringP.addLeftDir("foo", "bar/index.html") // "foo/bar/index.html"
P.addLeftDir("foo", "") // "foo/"
withLeftDir :: String -> String -> StringP.withLeftDir("qux", "foo/bar/index.html") // "qux/bar/index.html"
P.withLeftDir("qux", "index.html") // "qux/index.html"
P.withLeftDir("qux", "") // "qux/"
withRightDir :: String -> String -> StringP.withRightDir("qux", "foo/bar/index.html") // "foo/qux/index.html"
P.withRightDir("qux", "index.html") // "qux/index.html"
P.withRightDir("qux", "") // "qux/"
dropLeftDir :: String -> StringP.addRightDir("bar", "foo/index.html") // "foo/bar/index.html"
P.addRightDir("bar", "") // "bar/"
dropRightDir :: String -> StringP.dropRightDir("foo/bar/index.html") // "foo/index.html"
P.dropRightDir("index.html") // "index.html"
withDir :: String -> String -> StringP.withDir("bar", "foo/index.html") // "bar/index.html"
P.withDir("bar", "") // "bar/"
withBase :: String -> String -> StringP.withBase("index", "foo/page.html") // "foo/index"
P.withBase("index", "") // "index"
withName :: String -> StringP.withName("index", "foo/page.html") // "foo/index.html"
P.withName("index", "") // "index"
withExt :: String -> StringP.withExt(".html", "foo/index.md") // "foo/index.html"
P.withExt(".html", "") // ".html"
dropBase :: String -> StringP.dropBase("foo/bar/index.html") // "foo/bar/"
P.dropBase("index.html") // ""
dropExt :: String -> StringP.dropExt("foo/bar/index.html") // "foo/bar/index"
P.dropExt(".gitignore") // ".gitignore"
padNumeric :: Number -> StringP.padNumeric(4, "x") // "x"
P.padNumeric(4, "1") // "0001"
padName :: Number -> StringP.padName(2, "1.1.foo.js") // "01.01.foo.js"
padPath :: Number -> StringP.padPath(2, "1.folder/file.1.md") // "01.folder/file.01.md"
delimiter: low-level, import directlyposix: low-level, import directlysep: low-level, import directlywin32: low-level, import directlybasename: wrapped, use P.base insteaddirname: wrapped, use P.dir insteadextname: wrapped, use P.ext insteadformat: wrapped, use P helpers insteadparse: wrapped, use P helpers insteadisAbsolute: reexportedjoin: reexportednormalize: reexportedrelative: reexportedresolve: reexportedFAQs
Functional utils for FS paths
We found that pathz demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.