Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
@jsenv/util
Advanced tools
Set of functions often needed when using Node.js.
This repository exists mostly to work with files relative to a directory with an approach that works on windows and linux filesystems as shown in the code example below.
import { readFileSync } from "fs"
import { resolveUrl, urlToFileSystemPath, assertAndNormalizeDirectoryUrl } from "@jsenv/util"
const directoryUrl = assertAndNormalizeDirectoryUrl(__dirname)
const packageFileUrl = resolveUrl("package.json", directoryUrl)
const packageFilePath = urlToFileSystemPath(packageFileUrl)
const packageFileBuffer = readFileSync(packageFilePath)
With times more functions were added, all util are documented below.
npm install @jsenv/util
In this package functions related to filesystem work with url string instead of a filesystem path.
const url = "file:///directory/file.js"
const filesystemPath = "/directory/file.js"
This allows function to manipulate a value that is the same across operating systems. Because on windows a filesystem path looks like C:\\directory\\file.js
while linux/mac equivalent looks like /directory/file.js
. Also url are standard. A standard is more robust and knowledge acquired on a standard is reusable.
You might also notice a slight preference for url string over url object in the documentation or codebase. This is a deliberate choice because over time it appeared that an url string is easier to work with. Certainly because a string is a well known primitive while an url object is a more complex structure.
const urlString = "file:///directory/file.js"
const urlObject = new URL("file:///directory/file.js")
This preference mostly comes from the debugging experience inside VSCode.
This documentation and source code uses a naming taken from url standard specifications with minor differences. The following graph links each term with the corresponding part in an url.
href ┌────────────────────────────────────────┴──────────────────────────────────────────────┐ origin │ ┌────────────┴──────────────┐ │ │ authority │ │ ┌───────────────┴───────────────────────────┐ │ │ │ host ressource │ │ ┌──────────┴────────────────┐ ┌──────────────┴────────┬────────┐ │ │ hostname │ pathname │ │ │ │ ┌──────────────┴────────────┐ │ ┌──────┴──────┐ │ │ protocol userinfo subdomain domain │ │ filename │ │ ┌─┴──┐ ┌───┴────┐ │ ┌────────┴───────┐ │ │ ┌───┴─────┐ │ │ scheme │username password lowerleveldomains secondleveldomain topleveldomain port dirname basename extension search hash ┌──┴───┐│┌──┴───┐ ┌──┴───┐ ┌──┬─┬─┴─────┬───┐┌───────┴───────┐ ┌──────┴──────┐┌┴┐┌────┴─────┐ ┌──┴───┐ ┌───┴───┐ ┌────┴────┐ ┌┴┐ │ │││ │ │ │ │ │ │ │ ││ │ │ ││ ││ │ │ │ │ │ │ │ │ │ scheme://username:password@test.abcdedgh.www.secondleveldomain.topleveldomain:123/hello/world/basename.extension?name=ferret#hash
assertAndNormalizeDirectoryUrl
is a function ensuring the received value can be normalized to a directory url string. This function is great to make a function accept various values as directory url and normalize it to a standard directory url like file:///directory/
. Jsenv uses it for every function having a directory url parameter.
import { assertAndNormalizeDirectoryUrl } from "@jsenv/util"
assertAndNormalizeDirectoryUrl("/directory") // file:///directory/
— source code at src/assertAndNormalizeDirectoryUrl.js.
assertAndNormalizeFileUrl
is a function ensuring the received value can be normalized to a file url string. This function is great to make a function accept various values as file url and normalize it to a standard file url like file:///directory/file.js
. Jsenv uses it for every function having a file url parameter.
import { assertAndNormalizeFileUrl } from "@jsenv/util"
assertAndNormalizeFileUrl("/directory/file.js") // file:///directory/file.js
— source code at src/assertAndNormalizeFileUrl.js.
assertDirectoryPresence
is an async function throwing if directory does not exists on the filesystem. This function is great to assert a directory existence before going further. Jsenv uses it to throw early when a directory presence is mandatory for a given function to work properly.
import { assertDirectoryPresence } from "@jsenv/util"
await assertDirectoryPresence("file:///Users/directory/")
— source code at src/assertDirectoryPresence.js.
assertFilePresence
is an async function throwing if a file does not exists on the filesystem. This function is great to assert a file existence before going further. Jsenv uses it to throw early when a file presence is mandatory for a given function to work properly.
import { assertFilePresence } from "@jsenv/util"
await assertFilePresence("file:///Users/directory/file.js")
— source code at src/assertFilePresence.js.
bufferToEtag
is a function receiving a buffer and converting it into an eTag. This function returns a hash (a small string) representing a file content. You can later check if the file content has changed by comparing a previously generated eTag with the current file content. Jsenv uses it to generate eTag headers and to know if a file content has changed in specific scenarios.
import { bufferToEtag } from "@jsenv/util"
const eTag = bufferToEtag(Buffer.from("Hello world"))
const otherEtag = bufferToEtag(Buffer.from("Hello world"))
eTag === otherEtag
— see Buffer documentation on Node.js
— see eTag documentation on MDN
— source code at src/bufferToEtag.js.
collectFiles
is an async function collectings a subset of files inside a directory.
import { collectFiles } from "@jsenv/util"
const files = await collectFiles({
directoryUrl: "file:///Users/you/directory",
specifierMetaMap: {
"./**/*.js": {
whatever: 42,
},
},
predicate: (meta) => {
return meta.whatever === 42
},
})
— source code at src/collectFiles.js.
comparePathnames
is a function compare two pathnames and returning which pathnames comes first in a filesystem.
import { comparePathnames } from "@jsenv/util"
const pathnames = ["a/b.js", "a.js"]
pathnames.sort(comparePathnames)
— source code at src/comparePathnames.js.
copyFileSystemNode
is an async function creating a copy of the filesystem node at a given destination
import { copyFileSystemNode } from "@jsenv/util"
await copyFileSystemNode(`file:///file.js`, "file:///destination/file.js")
await copyFileSystemNode(`file:///directory`, "file:///destination/directory")
— source code at src/copyFileSystemNode.js.
ensureEmptyDirectory
is an async function ensuring a directory is empty. It removes a directory content when it exists or create an empty directory.
This function was written for testing. It is meant to clean up a directory in case a previous test execution let some files and you want to clean them before running your test. Jsenv uses it in some tests involving the filesystem.
import { ensureEmptyDirectory } from "@jsenv/util"
await ensureEmptyDirectory(`file:///directory`)
— source code at src/ensureEmptyDirectory.js.
ensureParentDirectories
is an async function creating every directory leading to a file. This function is useful to ensure a given file directories exists before doing any operation on that file. Jsenv uses it to write file in directories that does not exists yet.
import { ensureParentDirectories } from "@jsenv/util"
await ensureParentDirectories(`file:///directory/subdirectory/file.js`)
— source code at src/ensureParentDirectories.js.
writeDirectory
is an async function creating a directory on the filesystem. writeDirectory
is equivalent to fs.promises.mkdir but accepts url strings as directory path.
import { writeDirectory } from "@jsenv/util"
await writeDirectory(`file:///directory`)
— source code at src/writeDirectory.js.
fileSystemPathToUrl
is a function returning a filesystem path from an url string. fileSystemPathToUrl
is equivalent to pathToFileURL from Node.js but returns string instead of url objects.
import { fileSystemPathToUrl } from "@jsenv/util"
fileSystemPathToUrl("/directory/file.js")
— source code at src/fileSystemPathToUrl.js.
isFileSystemPath
is a function returning a filesystem path from an url string.
import { isFileSystemPath } from "@jsenv/util"
isFileSystemPath("/directory/file.js") // true
isFileSystemPath("C:\\directory\\file.js") // true
isFileSystemPath("directory/file.js") // false
isFileSystemPath("file:///directory/file.js") // false
— source code at src/isFileSystemPath.js.
memoize
is a function wrapping an other function to ensure it is called once.
import { memoize } from "@jsenv/util"
let callCount = 0
const fn = memoize(async () => {
callCount++
const value = await Promise.resolve("hello")
return value
})
const firstCallValue = await fn()
const secondCallValue = await fn()
firstCallValue // "hello"
secondCallValue // "hello"
callCount // 1
— source code at src/memoize.js.
moveFileSystemNode
is an async function moving a filesystem node to a destination.
import { moveFileSystemNode } from "@jsenv/util"
await moveFileSystemNode("file:///file.js", "file:///destination/file.js")
await moveFileSystemNode("file:///directory", "file:///destination/directory")
— source code at src/moveFileSystemNode.js.
readDirectory
is an async function returning an array of string representing all filesystem nodes inside that directory.
import { readDirectory } from "@jsenv/util"
const content = await readDirectory("file:///directory")
— source code at src/readDirectory.js.
readFileSystemNodeModificationTime
is an async function returning a number of milliseconds representing the date when the file was modified.
import { readFileSystemNodeModificationTime } from "@jsenv/util"
const mtimeMs = await readFileSystemNodeModificationTime("file:///directory/file.js")
— source code at src/readFileSystemNodeModificationTime.js.
readFile
is an async function returning the content of a file as string, buffer, or json.
import { readFile } from "@jsenv/util"
const fileContentAsString = await readFile("file:///directory/file.json")
const fileContentAsBuffer = await readFile("file:///directory/file.json", { as: "buffer" })
const fileContentAsJSON = await readFile("file:///directory/file.json", { as: "json" })
— source code at src/readFile.js.
readFileSystemNodeStat
is an async function returning a filesystem node stats object. readFileSystemNodeStat
is equivalent to fs.promises.stats from Node.js but accepts url strings as file path.
import { readFileSystemNodeStat } from "@jsenv/util"
const stats = await readFileSystemNodeStat("file:///directory/file.js")
— see also stats object documentation on Node.js
— source code at src/readFileSystemNodeStat.js.
readSymbolicLink
is an async function returning a symbolic link target as url string.
import { readSymbolicLink } from "@jsenv/util"
const targetUrlOrRelativeUrl = await readSymbolicLink("file:///directory/link")
— see also symlink documentation on Node.js
— source code at src/readSymbolicLink.js.
registerDirectoryLifecycle
is a function watching a directory at a given path and calling added
, updated
, removed
according to what is happening inside that directory. Usually, filesystem takes less than 100ms to notify something has changed.
import { registerDirectoryLifecycle } from "@jsenv/util"
const contentMap = {}
const unregister = registerDirectoryLifecycle("file:///directory", {
added: ({ relativeUrl, type }) => {
contentMap[relativeUrl] = type
},
removed: ({ relativeUrl }) => {
delete contentMap[relativeUrl]
},
})
// you can call unregister when you want to stop watching the directory
unregister()
— source code at src/registerDirectoryLifecycle.js.
registerFileLifecycle
is a function watching a file and calling added
, updated
, removed
according to what is happening to that file. Usually, filesystem takes less than 100ms to notify something has changed.
import { readFileSync } from "fs"
import { registerFileLifecycle } from "@jsenv/file-watcher"
const filePath = "/file.config.json"
let currentConfig = null
const unregister = registerFileLifecycle(filePath, {
added: () => {
currentConfig = JSON.parse(String(readFileSync(filePath)))
},
updated: () => {
currentConfig = JSON.parse(String(readFileSync(filePath)))
},
removed: () => {
currentConfig = null
},
notifyExistent: true,
})
// you can call unregister() when you want to stop watching the file
unregister()
— source code at src/registerFileLifecycle.js.
removeFileSystemNode
is an async function removing a node (directory, file, symbolic link) from the filesystem.
import { removeFileSystemNode } from "@jsenv/util"
await removeFileSystemNode("file:///file.js")
await removeFileSystemNode("file:///directory")
— source code at src/removeFileSystemNode.js.
resolveDirectoryUrl
is a function resolving a relative url to an absolute directory url string. This function applies url resolution and ensure the returned url ends with a slash. Enforcing the trailing slash indicates explicitely that the url is a directory. file:///directory/whatever/
shows whatever
is a directory while file:///directory/whatever
is ambiguous. This specificity helps url resolution against a directory as shown in the code below.
const urlA = new URL("file.js", "file:///directory/")
const urlB = new URL("file.js", "file:///directory")
urlA.href // file:///directory/file.js
urlB.href // file:///file.js
import { resolveDirectoryUrl } from "@jsenv/util"
const directoryUrl = resolveDirectoryUrl("src", "file:///directory")
directoryUrl // file:///directory/src/
— source code at src/resolveDirectoryUrl.js.
resolveUrl
is a function resolving a relative url to an absolute url string. As explained before jsenv prefer to work with url string. When it comes to url resolution it implies to write code like String(new URL(relativeUrl, url))
. But it makes relativeUrl
and url
values less readable in the middle of String(new URL())
. resolveUrl
exists just to increase code readability.
import { resolveUrl } from "@jsenv/util"
resolveUrl("file.js", "file:///directory/")
— source code at src/resolveUrl.js.
urlIsInsideOf
is a function returning a boolean indicating if an url is inside an other url.
import { urlIsInsideOf } from "@jsenv/util"
urlIsInsideOf("file:///directory/file.js", "file:///directory/") // true
urlIsInsideOf("file:///file.js", "file:///directory/") // false
— source code at src/urlIsInsideOf.js.
urlToBasename
is receiving an url and returning its basename.
import { urlToBasename } from "@jsenv/util"
urlToBasename("file:///directory/file.js") // "file"
urlToBasename("file:///directory/") // "directory"
urlToBasename("http://example.com") // ""
— source code at src/urlToBasename.js.
urlToExtension
is receiving an url and returning its extension.
import { urlToExtension } from "@jsenv/util"
urlToExtension("file:///directory/file.js") // ".js"
urlToExtension("file:///directory/file.") // "."
urlToExtension("http://example.com/file") // ""
— source code at src/urlToExtension.js.
urlToFilename
is receiving an url and returning its filename.
import { urlToFilename } from "@jsenv/util"
urlToFilename("file:///directory/file.js") // "file.js"
urlToFilename("file:///directory/file.") // "file."
urlToFilename("http://example.com/file") // "file"
— source code at src/urlToFilename.js.
urlToFileSystemPath
is a function returning a filesystem path from an url. urlToFileSystemPath
is equivalent to pathToFileURL from Node.js but returns string instead of url objects.
import { urlToFileSystemPath } from "@jsenv/util"
urlToFileSystemPath("file:///directory/file.js")
— source code at src/urlToFileSystemPath.js.
urlToOrigin
is a function receiving an url and returning its origin.
import { urlToOrigin } from "@jsenv/util"
urlToOrigin("file:///directory/file.js") // "file://"
urlToOrigin("http://example.com/file.js") // "http://example.com"
— source code at src/urlToOrigin.js.
urlToParentUrl
is a function receiving an url and returning its parent url if any or the url itself.
import { urlToParentUrl } from "@jsenv/util"
urlToParentUrl("http://example.com/dir/file.js") // "http://example.com/dir/"
urlToParentUrl("http://example.com/dir/") // "http://example.com/"
urlToParentUrl("http://example.com/") // "http://example.com/"
— source code at src/urlToParentUrl.js.
urlToPathname
is a function receiving an url and returning its pathname.
import { urlToPathname } from "@jsenv/util"
urlToPathname("http://example.com/dir/file.js") // "/dir/file.js"
urlToPathname("http://example.com/dir/") // "/dir/"
urlToPathname("http://example.com/") // "/"
— source code at src/urlToPathname.js.
urlToRelativeUrl
is a function receiving two absolute urls and returning the first url relative to the second one. urlToRelativeUrl
is the url equivalent to path.relative from Node.js.
import { urlToRelativeUrl } from "@jsenv/util"
urlToRelativeUrl("file:///directory/file.js", "file:///directory/")
urlToRelativeUrl("http://example.com/directory/file.js", "http://example.com/directory/")
— source code at src/urlToRelativeUrl.js.
urlToRessource
is a function receiving an url and returning its ressource.
import { urlToRessource } from "@jsenv/util"
urlToRessource("http://example.com/dir/file.js?foo=bar#10") // "/dir/file.js?foo=bar#10"
urlToScheme
is a function receiving an url and returning its scheme.
import { urlToScheme } from "@jsenv/util"
urlToScheme("http://example.com") // "http"
urlToScheme("file:///dir/file.js") // "file"
urlToScheme("about:blank") // "about"
writeFile
is an async function writing file and its content on the filesystem. This function auto create file parent directories if they do not exists.
import { writeFile } from "@jsenv/util"
await writeFile("file:///directory/file.txt", "Hello world")
— source code at src/writeFile.js.
writeFileSystemNodeModificationTime
is an async function writing file and its content on the filesystem. writeFileSystemNodeModificationTime
is like fs.promises.utimes but accepts url strings as file path.
import { writeFileSystemNodeModificationTime } from "@jsenv/util"
await writeFileSystemNodeModificationTime("file:///directory/file.js", Date.now())
— source code at src/writeFileSystemNodeModificationTime.js.
writeSymbolicLink
is an async function writing a symlink link to a file or directory on the filesystem.
import { writeSymbolicLink } from "@jsenv/util"
await writeSymbolicLink("file:///foo.js", "./bar.js")
— see also symlink documentation on Node.js
— source code at src/writeSymbolicLink.js.
There is a few more functions but they are more specific, you probably don't need them: Advanced api
FAQs
Set of functions often needed when using Node.js.
The npm package @jsenv/util receives a total of 128 weekly downloads. As such, @jsenv/util popularity was classified as not popular.
We found that @jsenv/util demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers 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
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.