@jsenv/util
Version:
Set of functions often needed when using Node.js.
923 lines (595 loc) • 31.4 kB
Markdown
# util
Set of functions often needed when using Node.js.
[](https://github.com/jsenv/jsenv-util/packages)
[](https://www.npmjs.com/package/@jsenv/util)
[](https://github.com/jsenv/jsenv-util/actions?workflow=ci)
[](https://codecov.io/gh/jsenv/jsenv-util)
# Table of contents
- [Presentation](#Presentation)
- [Example](#Example)
- [Installation](#Installation)
- [Terminology](#Terminology)
- [assertAndNormalizeDirectoryUrl](#assertAndNormalizeDirectoryUrl)
- [assertAndNormalizeFileUrl](#assertAndNormalizeFileUrl)
- [assertDirectoryPresence](#assertDirectoryPresence)
- [assertFilePresence](#assertFilePresence)
- [bufferToEtag](#bufferToEtag)
- [collectFiles](#collectFiles)
- [comparePathnames](#comparePathnames)
- [copyFileSystemNode](#copyFileSystemNode)
- [ensureEmptyDirectory](#ensureEmptyDirectory)
- [ensureParentDirectories](#ensureParentDirectories)
- [fileSystemPathToUrl](#fileSystemPathToUrl)
- [isFileSystemPath](#isFileSystemPath)
- [moveFileSystemNode](#moveFileSystemNode)
- [readDirectory](#readDirectory)
- [readFile](#readFile)
- [readFileSystemNodeModificationTime](#readFileSystemNodeModificationTime)
- [readFileSystemNodeStat](#readFileSystemNodeStat)
- [readSymbolicLink](#readSymbolicLink)
- [registerDirectoryLifecycle](#registerDirectoryLifecycle)
- [registerFileLifecycle](#registerFileLifecycle)
- [removeFileSystemNode](#removeFileSystemNode)
- [resolveUrl](#resolveUrl)
- [urlIsInsideOf](#urlIsInsideOf)
- [urlToBasename](#urlToBasename)
- [urlToExtension](#urlToExtension)
- [urlToFilename](#urlToFilename)
- [urlToFileSystemPath](#urlToFileSystemPath)
- [urlToOrigin](#urlToOrigin)
- [urlToParentUrl](#urlToParentUrl)
- [urlToPathname](#urlToPathname)
- [urlToRelativeUrl](#urlToRelativeUrl)
- [urlToRessource](#urlToRessource)
- [urlToScheme](#urlToScheme)
- [writeDirectory](#writeDirectory)
- [writeFile](#writeFile)
- [writeFileSystemNodeModificationTime](#writeFileSystemNodeModificationTime)
- [writeSymbolicLink](#writeSymbolicLink)
- [Advanced api](#Advanced-api)
# Presentation
This repository provides utils functions needed to work with files. It has no external dependency and two preferences:
<details>
<summary>prefer url over filesystem path</summary>
An url is better than a filesystem path because it does not care about the underlying filesystem format.
- A file url: `file:///directory/file.js`
- A Windows file path: `C:\\directory\\file.js`
- A Linux file path: `/directory/file.js`
</details>
<details>
<summary>prefer url string over url object</summary>
There is a deliberate preference for url string over url object in the documentation and codebase.
```js
const urlString = "file:///directory/file.js"
const urlObject = new URL("file:///directory/file.js")
```
A string is a simpler primitive than an url object and it becomes important while debugging.
<details>
<summary>Screenshot of an url object while debugging</summary>

</details>
<details>
<summary>Screenshot of an url string while debugging</summary>

</details>
</details>
This repository also provides some utils around urls not provided by Node.js. For instance it exports [urlToRelativeUrl](#urlToRelativeUrl) which can be seen as the equivalent of [path.relative](https://nodejs.org/dist/latest-v15.x/docs/api/path.html#path_path_relative_from_to) for urls.
Finally exported functions fully support url, even url string while native `fs` module does not.
<details>
<summary>fs lack support for url string</summary>
`fs` module accepts url object since version 7.6 but not url string.

Passing an url string to a function from `fs` will always throw [ENOENT](https://nodejs.org/api/errors.html#errors_common_system_errors) error.
```js
import { readFileSync } from "fs"
readFileSync(import.meta.url) // throw ENOENT
```
```js
const { readFileSync } = require("fs")
readFileSync(`file://${__filename}`) // throw ENOENT
```
> Node.js made this choice for performance reasons but it hurts my productivity.
</details>
# Example
The code below is a basic example reading package.json file as buffer.
```js
import { readFileSync } from "fs"
import { resolveUrl, urlToFileSystemPath } from "@jsenv/util"
const packageFileUrl = resolveUrl("package.json", import.meta.url)
const packageFilePath = urlToFileSystemPath(packageFileUrl)
const packageFileBuffer = readFileSync(packageFilePath)
```
With times more functions were added, all util are documented a bit further.
# Installation
```console
npm install @jsenv/util
```
# Terminology
This documentation and source code uses some wording explained in this part.
## Urls parts
You can refer to figure below to see how each part of an url is named.
<pre>
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
</pre>
## fileSystemNode
`fileSystemNode` word is used when a function does not assume what it is going to interact with: file, directory, or something else. For example [copyFileSystemNode(fromUrl, toUrl, options)](#copyFileSystemNode) will take whatever is at `fromUrl` and copy it at `toUrl`.
# assertAndNormalizeDirectoryUrl
`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/`.
<details>
<summary>assertAndNormalizeDirectoryUrl code example</summary>
```js
import { assertAndNormalizeDirectoryUrl } from "@jsenv/util"
assertAndNormalizeDirectoryUrl("/directory") // file:///directory/
assertAndNormalizeDirectoryUrl("C:\\directory") // file://C:/directory/
```
[unit test](./test/assertAndNormalizeDirectoryUrl/assertAndNormalizeDirectoryUrl.test.js) • [implementation](./src/assertAndNormalizeDirectoryUrl.js)
</details>
# assertAndNormalizeFileUrl
`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`.
<details>
<summary>assertAndNormalizeFileUrl code example</summary>
```js
import { assertAndNormalizeFileUrl } from "@jsenv/util"
assertAndNormalizeFileUrl("/directory/file.js") // file:///directory/file.js
assertAndNormalizeFileUrl("C:\\directory\\file.js") // file:///C:/directory/file.js
```
[unit test](./test/assertAndNormalizeFileUrl/assertAndNormalizeFileUrl.test.js) • [implementation](./src/assertAndNormalizeFileUrl.js)
</details>
# assertDirectoryPresence
`assertDirectoryPresence` is an async function throwing if directory does not exists on the filesystem. This function is great when code expects a directory to exist before going further.
<details>
<summary>assertDirectoryPresence code example</summary>
```js
import { assertDirectoryPresence } from "@jsenv/util"
await assertDirectoryPresence("file:///Users/directory/")
```
[unit test](./test/assertDirectoryPresence/assertDirectoryPresence.test.js) • [implementation](./src/assertDirectoryPresence.js)
</details>
# assertFilePresence
`assertFilePresence` is an async function throwing if a file does not exists on the filesystem. This function is great to when code expects a file to exist before going further.
<details>
<summary>assertFilePresence code example</summary>
```js
import { assertFilePresence } from "@jsenv/util"
await assertFilePresence("file:///Users/directory/file.js")
```
[unit test](./test/assertFilePresence/assertFilePresence.test.js) • [implementation](./src/assertFilePresence.js)
</details>
# bufferToEtag
`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.
<details>
<summary>bufferToEtag code example</summary>
```js
import { bufferToEtag } from "@jsenv/util"
const eTag = bufferToEtag(Buffer.from("Hello world"))
const otherEtag = bufferToEtag(Buffer.from("Hello world"))
eTag === otherEtag // true
```
[unit test](./test/bufferToEtag/bufferToEtag.test.js) • [implementation](./src/bufferToEtag.js) • [Buffer documentation on Node.js](https://nodejs.org/docs/latest-v13.x/api/buffer.html) • [eTag documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag)
</details>
# collectFiles
`collectFiles` is an async function collectings a subset of files inside a directory.
<details>
<summary>collectFiles code example</summary>
```js
import { collectFiles } from "@jsenv/util"
const files = await collectFiles({
directoryUrl: "file:///Users/you/directory",
structuredMetaMap: {
whatever: {
"./**/*.js": 42,
},
},
predicate: (meta) => {
return meta.whatever === 42
},
})
```
[unit test](./test/collectFiles/collectFiles.test.js) • [implementation](./src/collectFiles.js)
</details>
# comparePathnames
`comparePathnames` is a function compare two pathnames and returning which pathnames comes first in a filesystem.
<details>
<summary>comparePathnames code example</summary>
```js
import { comparePathnames } from "@jsenv/util"
const pathnames = ["a/b.js", "a.js"]
pathnames.sort(comparePathnames)
```
[implementation](./src/comparePathnames.js)
</details>
# copyFileSystemNode
`copyFileSystemNode` is an async function creating a copy of the filesystem node at a given destination
<details>
<summary>copyFileSystemNode code example</summary>
```js
import { copyFileSystemNode } from "@jsenv/util"
await copyFileSystemNode(`file:///file.js`, "file:///destination/file.js")
await copyFileSystemNode(`file:///directory`, "file:///destination/directory")
```
[unit test](./test/copyFileSystemNode/copyFileSystemNode.test.js) • [implementation](./src/copyFileSystemNode.js)
</details>
# ensureEmptyDirectory
`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.
<details>
<summary>ensureEmptyDirectory code example</summary>
```js
import { ensureEmptyDirectory } from "@jsenv/util"
await ensureEmptyDirectory(`file:///directory`)
```
[unit test](./test/ensureEmptyDirectory/ensureEmptyDirectory.test.js) • [implementation](./src/ensureEmptyDirectory.js)
</details>
# ensureParentDirectories
`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.
<details>
<summary>ensureParentDirectories code example</summary>
```js
import { ensureParentDirectories } from "@jsenv/util"
await ensureParentDirectories(`file:///directory/subdirectory/file.js`)
```
[implementation](./src/ensureParentDirectories.js)
</details>
# writeDirectory
`writeDirectory` is an async function creating a directory on the filesystem. `writeDirectory` is equivalent to [fs.promises.mkdir](https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_fspromises_mkdir_path_options) but accepts url strings as directory path.
<details>
<summary>writeDirectory code example</summary>
```js
import { writeDirectory } from "@jsenv/util"
await writeDirectory(`file:///directory`)
```
[unit test](./test/writeDirectory/writeDirectory.test.js) • [implementation](./src/writeDirectory.js)
</details>
# fileSystemPathToUrl
`fileSystemPathToUrl` is a function returning a filesystem path from an url string. `fileSystemPathToUrl` is equivalent to [pathToFileURL from Node.js](https://nodejs.org/docs/latest-v13.x/api/url.html#url_url_pathtofileurl_path) but returns string instead of url objects.
<details>
<summary>fileSystemPathToUrl code example</summary>
```js
import { fileSystemPathToUrl } from "@jsenv/util"
fileSystemPathToUrl("/directory/file.js")
```
[unit test](./test/fileSystemPathToUrl/fileSystemPathToUrl.test.js) • [implementation](./src/fileSystemPathToUrl.js)
</details>
# isFileSystemPath
`isFileSystemPath` is a function receiving a string and returning a boolean indicating if this string is a filesystem path.
<details>
<summary>isFileSystemPath code example</summary>
```js
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
```
[unit test](./test/isFileSystemPath/isFileSystemPath.test.js) • [implementation](./src/isFileSystemPath.js)
</details>
# moveFileSystemNode
`moveFileSystemNode` is an async function moving a filesystem node to a destination.
<details>
<summary>moveFileSystemNode code example</summary>
```js
import { moveFileSystemNode } from "@jsenv/util"
await moveFileSystemNode("file:///file.js", "file:///destination/file.js")
await moveFileSystemNode("file:///directory", "file:///destination/directory")
```
[unit test](./test/moveFileSystemNode/moveFileSystemNode.test.js) • [implementation](./src/moveFileSystemNode.js)
</details>
# readDirectory
`readDirectory` is an async function returning an array of string representing all filesystem nodes inside that directory.
<details>
<summary>readDirectory code example</summary>
```js
import { readDirectory } from "@jsenv/util"
const content = await readDirectory("file:///directory")
```
[implementation](./src/readDirectory.js)
</details>
# readFileSystemNodeModificationTime
`readFileSystemNodeModificationTime` is an async function returning a number of milliseconds representing the date when the file was modified.
<details>
<summary>readFileSystemNodeModificationTime code example</summary>
```js
import { readFileSystemNodeModificationTime } from "@jsenv/util"
const mtimeMs = await readFileSystemNodeModificationTime("file:///directory/file.js")
```
[implementation](./src/readFileSystemNodeModificationTime.js)
</details>
# readFile
`readFile` is an async function returning the content of a file as string, buffer, or json.
<details>
<summary>readFile code example</summary>
```js
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" })
```
[unit test](./test/readFile/readFile.test.js) • [implementation](./src/readFile.js)
</details>
# readFileSystemNodeStat
`readFileSystemNodeStat` is an async function returning a filesystem node stats object. `readFileSystemNodeStat` is equivalent to [fs.promises.stats from Node.js](https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_fspromises_stat_path_options) but accepts url strings as file path.
<details>
<summary>readFileSystemNodeStat code example</summary>
```js
import { readFileSystemNodeStat } from "@jsenv/util"
const stats = await readFileSystemNodeStat("file:///directory/file.js")
```
[unit test](./test/readFileSystemNodeStat/readFileSystemNodeStat.test.js) • [implementation](./src/readFileSystemNodeStat.js) • [stats object documentation on Node.js](https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_class_fs_stats)
</details>
# readSymbolicLink
`readSymbolicLink` is an async function returning a symbolic link target as url string.
<details>
<summary>readFileSystemNodeStat code example</summary>
```js
import { readSymbolicLink } from "@jsenv/util"
const targetUrlOrRelativeUrl = await readSymbolicLink("file:///directory/link")
```
[implementation](./src/readSymbolicLink.js) • [symlink documentation on Node.js](https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_fs_symlink_target_path_type_callback)
</details>
# registerDirectoryLifecycle
`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.
<details>
<summary>registerDirectoryLifecycle code example</summary>
```js
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()
```
[unit test](./test/registerDirectoryLifecycle/registerDirectoryLifecycle.test.js) • [implementation](./src/registerDirectoryLifecycle.js)
</details>
# registerFileLifecycle
`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.
<details>
<summary>registerFileLifecycle code example</summary>
```js
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()
```
[unit test](./test/registerFileLifecycle/registerFileLifecycle.test.js) • [implementation](./src/registerFileLifecycle.js)
</details>
# removeFileSystemNode
`removeFileSystemNode` is an async function removing a node (directory, file, symbolic link) from the filesystem.
<details>
<summary>removeFileSystemNode code example</summary>
```js
import { removeFileSystemNode } from "@jsenv/util"
await removeFileSystemNode("file:///file.js")
await removeFileSystemNode("file:///directory")
```
[unit test](./test/removeFileSystemNode/removeFileSystemNode.test.js) • [implementation](./src/removeFileSystemNode.js)
</details>
# resolveUrl
`resolveUrl` is a function receiving two arguments called `specifier` and `baseUrl`. Both arguments are **required**. `resolveUrl` applies url resolution between `specifier` and `baseUrl` and returns the corresponding absolute url string.
<details>
<summary>resolveUrl code example</summary>
```js
import { resolveUrl } from "@jsenv/util"
resolveUrl("file.js", "file:///directory/") // file:///directory/file.js
```
[unit test](./test/resolveUrl/resolveUrl.test.js) • [implementation](./src/resolveUrl.js)
</details>
<details>
<summary>Note about url resolution and directory</summary>
When working with directory urls, it is important to have a trailing `/`.
```js
new URL("foo.js", "file:///dir").href // file:///foo.js
new URL("foo.js", `file:///dir/`).href // file:///dir/foo.js
```
For this reason, if you have a variable holding a directory url, be sure to put a trailing slash.
```js
import { resolveUrl } from "@jsenv/util"
const directoryUrl = resolveUrl("./dir/", "file:///")
```
</details>
<details>
<summary>Difference between resolveUrl and URL</summary>
Using `resolveUrl` means code wants to perform url resolution between something that can be relative: `specifier`, and something absolute: `baseUrl`.
For this reason `resolveUrl` will throw if `baseUrl` is `undefined`. This is a major difference with `URL` constructor that would not throw in such case.
```js
import { resolveUrl } from "@jsenv/util"
new URL("http://example.com", undefined) // does not throw
resolveUrl("http://example.com", undefined) // throw "baseUrl is missing to resolve http://example.com"
```
Technically, `http://example.com` is already absolute and does not need a `baseUrl` to be resolved. But, receiving `undefined` when an absolute url was expected indicates there is something wrong in the code.
This is a feature that helps to catch bugs.
</details>
# urlIsInsideOf
`urlIsInsideOf` is a function returning a boolean indicating if an url is inside an other url.
<details>
<summary>urlIsInsideOf code example</summary>
```js
import { urlIsInsideOf } from "@jsenv/util"
urlIsInsideOf("file:///directory/file.js", "file:///directory/") // true
urlIsInsideOf("file:///file.js", "file:///directory/") // false
```
[unit test](./test/urlIsInsideOf/urlIsInsideOf.test.js) • [implementation](./src/urlIsInsideOf.js)
</details>
# urlToBasename
`urlToBasename` is receiving an url and returning its basename.
<details>
<summary>urlToBasename code example</summary>
```js
import { urlToBasename } from "@jsenv/util"
urlToBasename("file:///directory/file.js") // "file"
urlToBasename("file:///directory/") // "directory"
urlToBasename("http://example.com") // ""
```
[unit test](./test/urlToBasename/urlToBasename.test.js) • [implementation](./src/urlToBasename.js)
</details>
# urlToExtension
`urlToExtension` is receiving an url and returning its extension.
<details>
<summary>urlToExtension code example</summary>
```js
import { urlToExtension } from "@jsenv/util"
urlToExtension("file:///directory/file.js") // ".js"
urlToExtension("file:///directory/file.") // "."
urlToExtension("http://example.com/file") // ""
```
[unit test](./test/urlToExtension/urlToExtension.test.js) • [implementation](./src/urlToExtension.js)
</details>
# urlToFilename
`urlToFilename` is receiving an url and returning its filename.
<details>
<summary>urlToFilename code example</summary>
```js
import { urlToFilename } from "@jsenv/util"
urlToFilename("file:///directory/file.js") // "file.js"
urlToFilename("file:///directory/file.") // "file."
urlToFilename("http://example.com/file") // "file"
```
[unit test](./test/urlToFilename/urlToFilename.test.js) • [implementation](./src/urlToFilename.js)
</details>
# urlToFileSystemPath
`urlToFileSystemPath` is a function returning a filesystem path from an url. `urlToFileSystemPath` is equivalent to [pathToFileURL from Node.js](https://nodejs.org/docs/latest-v13.x/api/url.html#url_url_pathtofileurl_path) but returns string instead of url objects.
<details>
<summary>urlToFileSystemPath code example</summary>
```js
import { urlToFileSystemPath } from "@jsenv/util"
// on mac or linux
urlToFileSystemPath("file:///directory/file.js") // /directory/file.js
// on windows
urlToFileSystemPath("file://C:/directory/file.js") // C:\\directory\\file.js
```
[unit test](./test/urlToFileSystemPath/urlToFileSystemPath.test.js) • [implementation](./src/urlToFileSystemPath.js)
</details>
# urlToOrigin
`urlToOrigin` is a function receiving an url and returning its origin.
<details>
<summary>urlToOrigin code example</summary>
```js
import { urlToOrigin } from "@jsenv/util"
urlToOrigin("file:///directory/file.js") // "file://"
urlToOrigin("http://example.com/file.js") // "http://example.com"
```
[unit test](./test/urlToOrigin/urlToOrigin.test.js) • [implementation](./src/urlToOrigin.js)
</details>
# urlToParentUrl
`urlToParentUrl` is a function receiving an url and returning its parent url if any or the url itself.
<details>
<summary>urlToParentUrl code example</summary>
```js
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/"
```
[unit test](./test/urlToParentUrl/urlToParentUrl.test.js) • [implementation](./src/urlToParentUrl.js)
</details>
# urlToPathname
`urlToPathname` is a function receiving an url and returning its pathname.
<details>
<summary>urlToPathname code example</summary>
```js
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/") // "/"
```
[unit test](./test/urlToPathname/urlToPathname.test.js) • [implementation](./src/urlToPathname.js)
</details>
# urlToRelativeUrl
`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](https://nodejs.org/docs/latest-v13.x/api/path.html#path_path_relative_from_to).
<details>
<summary>urlToRelativeUrl code example</summary>
```js
import { urlToRelativeUrl } from "@jsenv/util"
urlToRelativeUrl("file:///directory/file.js", "file:///directory/") // file.js
urlToRelativeUrl("file:///directory/index.js", "file:///directory/foo/file.js") // ../index.js
```
[unit test](./test/urlToRelativeUrl/urlToRelativeUrl.test.js) • [implementation](./src/urlToRelativeUrl.js)
</details>
# urlToRessource
`urlToRessource` is a function receiving an url and returning its ressource.
<details>
<summary>urlToRessource code example</summary>
```js
import { urlToRessource } from "@jsenv/util"
urlToRessource("http://example.com/dir/file.js?foo=bar#10") // "/dir/file.js?foo=bar#10"
```
[unit test](./test/urlToRessource/urlToRessource.test.js) • [implementation](./src/urlToRessource.js)
</details>
# urlToScheme
`urlToScheme` is a function receiving an url and returning its scheme.
<details>
<summary>urlToScheme code example</summary>
```js
import { urlToScheme } from "@jsenv/util"
urlToScheme("http://example.com") // "http"
urlToScheme("file:///dir/file.js") // "file"
urlToScheme("about:blank") // "about"
```
[unit test](./test/urlToScheme/urlToScheme.test.js) • [implementation](./src/urlToScheme.js)
</details>
# writeFile
`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.
<details>
<summary>writeFile code example</summary>
```js
import { writeFile } from "@jsenv/util"
await writeFile("file:///directory/file.txt", "Hello world")
```
[unit test](./test/writeFile/writeFile.test.js) • [implementation](./src/writeFile.js)
</details>
# writeFileSystemNodeModificationTime
`writeFileSystemNodeModificationTime` is an async function writing file and its content on the filesystem. `writeFileSystemNodeModificationTime` is like [fs.promises.utimes](https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_fspromises_utimes_path_atime_mtime) but accepts url strings as file path.
<details>
<summary>writeFileSystemNodeModificationTime code example</summary>
```js
import { writeFileSystemNodeModificationTime } from "@jsenv/util"
await writeFileSystemNodeModificationTime("file:///directory/file.js", Date.now())
```
[unit test](./test/writeFileSystemNodeModificationTime/writeFileSystemNodeModificationTime.test.js) • [implementation](./src/writeFileSystemNodeModificationTime.js)
</details>
# writeSymbolicLink
`writeSymbolicLink` is an async function writing a symlink link to a file or directory on the filesystem.
<details>
<summary>writeSymbolicLink code example</summary>
```js
import { writeSymbolicLink } from "@jsenv/util"
await writeSymbolicLink("file:///foo.js", "./bar.js")
```
[implementation](./src/writeFileSystemNodeModificationTime.js) • [symlink documentation on Node.js](https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_fs_symlink_target_path_type_callback)
</details>
# Advanced api
There is a few more functions but they are more specific, you probably don't need them: [Advanced api](./docs/internal-api.md)