Socket
Socket
Sign inDemoInstall

@jsenv/filesystem

Package Overview
Dependencies
2
Maintainers
2
Versions
62
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.0 to 2.0.0

2

package.json
{
"name": "@jsenv/filesystem",
"version": "1.0.0",
"version": "2.0.0",
"description": "Collection of functions to interact with filesystem in Node.js",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -6,3 +6,3 @@ # Jsenv filesystem

[![npm package](https://img.shields.io/npm/v/@jsenv/filesystem.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/filesystem)
[![github main](https://github.com/jsenv/filesystem/workflows/main/badge.svg)](https://github.com/jsenv/jsenv-filesystem/actions?workflow=main)
[![github main](https://github.com/jsenv/filesystem/workflows/main/badge.svg)](https://github.com/jsenv/filesystem/actions?workflow=main)
[![codecov coverage](https://codecov.io/gh/jsenv/filesystem/branch/main/graph/badge.svg)](https://codecov.io/gh/jsenv/filesystem)

@@ -9,0 +9,0 @@

/* eslint-disable import/max-dependencies */
import { copyFile as copyFileNode } from "fs"
import { copyFile as copyFileNode } from "node:fs"
import { urlTargetsSameFileSystemPath } from "./internal/urlTargetsSameFileSystemPath.js"

@@ -22,19 +23,18 @@ import { statsToType } from "./internal/statsToType.js"

export const copyFileSystemNode = async (
source,
destination,
{
overwrite = false,
preserveStat = true,
preserveMtime = preserveStat,
preservePermissions = preserveStat,
allowUseless = false,
followLink = true,
} = {},
) => {
const sourceUrl = assertAndNormalizeFileUrl(source)
let destinationUrl = assertAndNormalizeFileUrl(destination)
const sourcePath = urlToFileSystemPath(sourceUrl)
export const copyFileSystemNode = async ({
from,
to,
overwrite = false,
preserveStat = true,
preserveMtime = preserveStat,
preservePermissions = preserveStat,
allowUseless = false,
followLink = true,
}) => {
const fromUrl = assertAndNormalizeFileUrl(from)
const fromPath = urlToFileSystemPath(fromUrl)
let toUrl = assertAndNormalizeFileUrl(to)
let toPath = urlToFileSystemPath(toUrl)
const sourceStats = await readFileSystemNodeStat(sourceUrl, {
const sourceStats = await readFileSystemNodeStat(fromUrl, {
nullIfNotFound: true,

@@ -44,6 +44,6 @@ followLink: false,

if (!sourceStats) {
throw new Error(`nothing to copy at ${sourcePath}`)
throw new Error(`nothing to copy at ${fromPath}`)
}
let destinationStats = await readFileSystemNodeStat(destinationUrl, {
let destinationStats = await readFileSystemNodeStat(toUrl, {
nullIfNotFound: true,

@@ -56,13 +56,13 @@ // we force false here but in fact we will follow the destination link

if (followLink && destinationStats && destinationStats.isSymbolicLink()) {
const target = await readSymbolicLink(destinationUrl)
destinationUrl = resolveUrl(target, destinationUrl)
destinationStats = await readFileSystemNodeStat(destinationUrl, { nullIfNotFound: true })
const linkTarget = await readSymbolicLink(toUrl)
toUrl = resolveUrl(linkTarget, toUrl)
toPath = urlToFileSystemPath(toUrl)
destinationStats = await readFileSystemNodeStat(toUrl, { nullIfNotFound: true })
}
const destinationPath = urlToFileSystemPath(destinationUrl)
if (urlTargetsSameFileSystemPath(sourceUrl, destinationUrl)) {
if (urlTargetsSameFileSystemPath(fromUrl, toUrl)) {
if (allowUseless) {
return
}
throw new Error(`cannot copy ${sourcePath} because destination and source are the same`)
throw new Error(`cannot copy ${fromPath} because destination and source are the same`)
}

@@ -76,3 +76,3 @@

throw new Error(
`cannot copy ${sourceType} from ${sourcePath} to ${destinationPath} because destination exists and is not a ${sourceType} (it's a ${destinationType})`,
`cannot copy ${sourceType} from ${fromPath} to ${toPath} because destination exists and is not a ${sourceType} (it's a ${destinationType})`,
)

@@ -82,3 +82,3 @@ }

throw new Error(
`cannot copy ${sourceType} from ${sourcePath} to ${destinationPath} because destination exists and overwrite option is disabled`,
`cannot copy ${sourceType} from ${fromPath} to ${toPath} because destination exists and overwrite option is disabled`,
)

@@ -88,9 +88,9 @@ }

// remove file, link, directory...
await removeFileSystemNode(destinationUrl, { recursive: true, allowUseless: true })
await removeFileSystemNode(toUrl, { recursive: true, allowUseless: true })
} else {
await ensureParentDirectories(destinationUrl)
await ensureParentDirectories(toUrl)
}
if (sourceStats.isDirectory()) {
destinationUrl = ensureUrlTrailingSlash(destinationUrl)
toUrl = ensureUrlTrailingSlash(toUrl)
}

@@ -109,4 +109,4 @@

const visitFile = async (fileUrl, fileStats) => {
const fileRelativeUrl = urlToRelativeUrl(fileUrl, sourceUrl)
const fileCopyUrl = resolveUrl(fileRelativeUrl, destinationUrl)
const fileRelativeUrl = urlToRelativeUrl(fileUrl, fromUrl)
const fileCopyUrl = resolveUrl(fileRelativeUrl, toUrl)

@@ -118,3 +118,3 @@ await copyFileContentNaive(urlToFileSystemPath(fileUrl), urlToFileSystemPath(fileCopyUrl))

const visitSymbolicLink = async (symbolicLinkUrl) => {
const symbolicLinkRelativeUrl = urlToRelativeUrl(symbolicLinkUrl, sourceUrl)
const symbolicLinkRelativeUrl = urlToRelativeUrl(symbolicLinkUrl, fromUrl)
const symbolicLinkTarget = await readSymbolicLink(symbolicLinkUrl)

@@ -126,11 +126,11 @@ const symbolicLinkTargetUrl = resolveUrl(symbolicLinkTarget, symbolicLinkUrl)

let symbolicLinkCopyTarget
if (symbolicLinkTargetUrl === sourceUrl) {
symbolicLinkCopyTarget = linkIsRelative ? symbolicLinkTarget : destinationUrl
} else if (urlIsInsideOf(symbolicLinkTargetUrl, sourceUrl)) {
if (symbolicLinkTargetUrl === fromUrl) {
symbolicLinkCopyTarget = linkIsRelative ? symbolicLinkTarget : toUrl
} else if (urlIsInsideOf(symbolicLinkTargetUrl, fromUrl)) {
// symbolic link targets something inside the directory we want to copy
// reflects it inside the copied directory structure
const linkCopyTargetRelative = urlToRelativeUrl(symbolicLinkTargetUrl, sourceUrl)
const linkCopyTargetRelative = urlToRelativeUrl(symbolicLinkTargetUrl, fromUrl)
symbolicLinkCopyTarget = linkIsRelative
? `./${linkCopyTargetRelative}`
: resolveUrl(linkCopyTargetRelative, destinationUrl)
: resolveUrl(linkCopyTargetRelative, toUrl)
} else {

@@ -150,14 +150,18 @@ // symbolic link targets something outside the directory we want to copy

const symbolicLinkCopyUrl = resolveUrl(symbolicLinkRelativeUrl, destinationUrl)
await writeSymbolicLink(symbolicLinkCopyUrl, symbolicLinkCopyTarget, { type: linkType })
const symbolicLinkCopyUrl = resolveUrl(symbolicLinkRelativeUrl, toUrl)
await writeSymbolicLink({
from: symbolicLinkCopyUrl,
to: symbolicLinkCopyTarget,
type: linkType,
})
}
const copyStats = async (destinationUrl, stats) => {
const copyStats = async (toUrl, stats) => {
if (preservePermissions || preserveMtime) {
const { mode, mtimeMs } = stats
if (preservePermissions) {
await writeFileSystemNodePermissions(destinationUrl, binaryFlagsToPermissions(mode))
await writeFileSystemNodePermissions(toUrl, binaryFlagsToPermissions(mode))
}
if (preserveMtime) {
await writeFileSystemNodeModificationTime(destinationUrl, mtimeMs)
await writeFileSystemNodeModificationTime(toUrl, mtimeMs)
}

@@ -168,4 +172,4 @@ }

const visitDirectory = async (directoryUrl, directoryStats) => {
const directoryRelativeUrl = urlToRelativeUrl(directoryUrl, sourceUrl)
const directoryCopyUrl = resolveUrl(directoryRelativeUrl, destinationUrl)
const directoryRelativeUrl = urlToRelativeUrl(directoryUrl, fromUrl)
const directoryCopyUrl = resolveUrl(directoryRelativeUrl, toUrl)

@@ -188,3 +192,3 @@ await writeDirectory(directoryCopyUrl)

await visit(sourceUrl, sourceStats)
await visit(fromUrl, sourceStats)
}

@@ -191,0 +195,0 @@

@@ -6,3 +6,6 @@ export const isFileSystemPath = (value) => {

if (value[0] === "/") return true
if (value[0] === "/") {
return true
}
return startsWithWindowsDriveLetter(value)

@@ -9,0 +12,0 @@ }

@@ -12,12 +12,9 @@ import { assertAndNormalizeDirectoryUrl } from "./assertAndNormalizeDirectoryUrl.js"

export const moveDirectoryContent = async (
source,
destination,
{ overwrite, followLink = true } = {},
) => {
const sourceUrl = assertAndNormalizeDirectoryUrl(source)
let destinationUrl = assertAndNormalizeDirectoryUrl(destination)
const sourcePath = urlToFileSystemPath(sourceUrl)
export const moveDirectoryContent = async ({ from, to, overwrite, followLink = true } = {}) => {
const fromUrl = assertAndNormalizeDirectoryUrl(from)
const fromPath = urlToFileSystemPath(fromUrl)
let toUrl = assertAndNormalizeDirectoryUrl(to)
let toPath = urlToFileSystemPath(toUrl)
const sourceStats = await readFileSystemNodeStat(sourceUrl, {
const sourceStats = await readFileSystemNodeStat(fromUrl, {
nullIfNotFound: true,

@@ -27,10 +24,10 @@ followLink: false,

if (!sourceStats) {
throw new Error(`no directory to move content from at ${sourcePath}`)
throw new Error(`no directory to move content from at ${fromPath}`)
}
if (!sourceStats.isDirectory()) {
const sourceType = statsToType(sourceStats)
throw new Error(`found a ${sourceType} instead of a directory at ${sourcePath}`)
throw new Error(`found a ${sourceType} instead of a directory at ${fromPath}`)
}
let destinationStats = await readFileSystemNodeStat(destinationUrl, {
let destinationStats = await readFileSystemNodeStat(toUrl, {
nullIfNotFound: true,

@@ -42,31 +39,35 @@ // we force false here but in fact we will follow the destination link

if (followLink && destinationStats && destinationStats.isSymbolicLink()) {
const target = await readSymbolicLink(destinationUrl)
destinationUrl = resolveUrl(target, destinationUrl)
destinationStats = await readFileSystemNodeStat(destinationUrl, { nullIfNotFound: true })
const linkTarget = await readSymbolicLink(toUrl)
toUrl = resolveUrl(linkTarget, toUrl)
toPath = urlToFileSystemPath(toUrl)
destinationStats = await readFileSystemNodeStat(toUrl, { nullIfNotFound: true })
}
const destinationPath = urlToFileSystemPath(destinationUrl)
if (destinationStats === null) {
throw new Error(`no directory to move content into at ${destinationPath}`)
throw new Error(`no directory to move content into at ${toPath}`)
}
if (!destinationStats.isDirectory()) {
const destinationType = statsToType(destinationStats)
throw new Error(
`destination leads to a ${destinationType} instead of a directory at ${destinationPath}`,
)
throw new Error(`destination leads to a ${destinationType} instead of a directory at ${toPath}`)
}
if (urlTargetsSameFileSystemPath(sourceUrl, destinationUrl)) {
if (urlTargetsSameFileSystemPath(fromUrl, toUrl)) {
throw new Error(
`cannot move directory content, source and destination are the same (${sourcePath})`,
`cannot move directory content, source and destination are the same (${fromPath})`,
)
}
const directoryEntries = await readDirectory(sourceUrl)
const directoryEntries = await readDirectory(fromUrl)
await Promise.all(
directoryEntries.map(async (directoryEntry) => {
const from = resolveUrl(directoryEntry, sourceUrl)
const to = resolveUrl(directoryEntry, destinationUrl)
await moveFileSystemNode(from, to, { overwrite, followLink })
const from = resolveUrl(directoryEntry, fromUrl)
const to = resolveUrl(directoryEntry, toUrl)
await moveFileSystemNode({
from,
to,
overwrite,
followLink,
})
}),
)
}
/* eslint-disable import/max-dependencies */
import { rename } from "fs"
import { rename } from "node:fs"
import { urlTargetsSameFileSystemPath } from "./internal/urlTargetsSameFileSystemPath.js"

@@ -14,12 +15,15 @@ import { statsToType } from "./internal/statsToType.js"

export const moveFileSystemNode = async (
source,
destination,
{ overwrite = false, allowUseless = false, followLink = true } = {},
) => {
const sourceUrl = assertAndNormalizeFileUrl(source)
let destinationUrl = assertAndNormalizeFileUrl(destination)
const sourcePath = urlToFileSystemPath(sourceUrl)
export const moveFileSystemNode = async ({
from,
to,
overwrite = false,
allowUseless = false,
followLink = true,
}) => {
const fromUrl = assertAndNormalizeFileUrl(from)
const fromPath = urlToFileSystemPath(fromUrl)
let toUrl = assertAndNormalizeFileUrl(to)
let toPath = urlToFileSystemPath(toUrl)
const sourceStats = await readFileSystemNodeStat(sourceUrl, {
const sourceStats = await readFileSystemNodeStat(fromUrl, {
nullIfNotFound: true,

@@ -29,6 +33,6 @@ followLink: false,

if (!sourceStats) {
throw new Error(`nothing to move from ${sourcePath}`)
throw new Error(`nothing to move from ${fromPath}`)
}
let destinationStats = await readFileSystemNodeStat(destinationUrl, {
let destinationStats = await readFileSystemNodeStat(toUrl, {
nullIfNotFound: true,

@@ -41,13 +45,13 @@ // we force false here but in fact we will follow the destination link

if (followLink && destinationStats && destinationStats.isSymbolicLink()) {
const target = await readSymbolicLink(destinationUrl)
destinationUrl = resolveUrl(target, destinationUrl)
destinationStats = await readFileSystemNodeStat(destinationUrl, { nullIfNotFound: true })
const linkTarget = await readSymbolicLink(toUrl)
toUrl = resolveUrl(linkTarget, toUrl)
toPath = urlToFileSystemPath(toUrl)
destinationStats = await readFileSystemNodeStat(toUrl, { nullIfNotFound: true })
}
const destinationPath = urlToFileSystemPath(destinationUrl)
if (urlTargetsSameFileSystemPath(sourceUrl, destinationUrl)) {
if (urlTargetsSameFileSystemPath(fromUrl, toUrl)) {
if (allowUseless) {
return
}
throw new Error(`no move needed for ${sourcePath} because destination and source are the same`)
throw new Error(`no move needed for ${fromPath} because destination and source are the same`)
}

@@ -61,3 +65,3 @@

throw new Error(
`cannot move ${sourceType} from ${sourcePath} to ${destinationPath} because destination exists and is not a ${sourceType} (it's a ${destinationType})`,
`cannot move ${sourceType} from ${fromPath} to ${toPath} because destination exists and is not a ${sourceType} (it's a ${destinationType})`,
)

@@ -67,3 +71,3 @@ }

throw new Error(
`cannot move ${sourceType} from ${sourcePath} to ${destinationPath} because destination exists and overwrite option is disabled`,
`cannot move ${sourceType} from ${fromPath} to ${toPath} because destination exists and overwrite option is disabled`,
)

@@ -73,11 +77,15 @@ }

// remove file, link, directory...
await removeFileSystemNode(destinationUrl, { recursive: true })
await removeFileSystemNode(toUrl, { recursive: true })
} else {
await ensureParentDirectories(destinationUrl)
await ensureParentDirectories(toUrl)
}
await moveNaive(sourcePath, destinationPath, {
await moveNaive(fromPath, toPath, {
handleCrossDeviceError: async () => {
await copyFileSystemNode(sourceUrl, destinationUrl, { preserveStat: true })
await removeFileSystemNode(sourceUrl, { recursive: true })
await copyFileSystemNode({
from: fromUrl,
to: toUrl,
preserveStat: true,
})
await removeFileSystemNode(fromUrl, { recursive: true })
},

@@ -87,5 +95,5 @@ })

const moveNaive = (sourcePath, destinationPath, { handleCrossDeviceError = null } = {}) => {
const moveNaive = (fromPath, destinationPath, { handleCrossDeviceError = null } = {}) => {
return new Promise((resolve, reject) => {
rename(sourcePath, destinationPath, (error) => {
rename(fromPath, destinationPath, (error) => {
if (error) {

@@ -92,0 +100,0 @@ if (handleCrossDeviceError && error.code === "EXDEV") {

@@ -1,11 +0,11 @@

export const urlIsInsideOf = (urlValue, otherUrlValue) => {
const url = new URL(urlValue)
const otherUrl = new URL(otherUrlValue)
export const urlIsInsideOf = (url, otherUrl) => {
const urlObject = new URL(url)
const otherUrlObject = new URL(otherUrl)
if (url.origin !== otherUrl.origin) {
if (urlObject.origin !== otherUrlObject.origin) {
return false
}
const urlPathname = url.pathname
const otherUrlPathname = otherUrl.pathname
const urlPathname = urlObject.pathname
const otherUrlPathname = otherUrlObject.pathname
if (urlPathname === otherUrlPathname) {

@@ -15,3 +15,4 @@ return false

return urlPathname.startsWith(otherUrlPathname)
const isInside = urlPathname.startsWith(otherUrlPathname)
return isInside
}
import { fileURLToPath } from "url"
export const urlToFileSystemPath = (fileUrl) => {
if (fileUrl[fileUrl.length - 1] === "/") {
export const urlToFileSystemPath = (url) => {
let urlString = String(url)
if (urlString[urlString.length - 1] === "/") {
// remove trailing / so that nodejs path becomes predictable otherwise it logs
// the trailing slash on linux but does not on windows
fileUrl = fileUrl.slice(0, -1)
urlString = urlString.slice(0, -1)
}
const fileSystemPath = fileURLToPath(fileUrl)
const fileSystemPath = fileURLToPath(urlString)
return fileSystemPath
}
export const urlToOrigin = (url) => {
if (url.startsWith("file://")) {
const urlString = String(url)
if (urlString.startsWith("file://")) {
return `file://`
}
return new URL(url).origin
return new URL(urlString).origin
}

@@ -8,3 +8,4 @@ import { urlToOrigin } from "./urlToOrigin.js"

if (slashLastIndex === -1) {
return url
const urlAsString = String(url)
return urlAsString
}

@@ -16,12 +17,14 @@

if (slashPreviousIndex === -1) {
return url
const urlAsString = String(url)
return urlAsString
}
const origin = urlToOrigin(url)
return `${origin}${ressource.slice(0, slashPreviousIndex + 1)}`
const parentUrl = `${origin}${ressource.slice(0, slashPreviousIndex + 1)}`
return parentUrl
}
const origin = urlToOrigin(url)
return `${origin}${ressource.slice(0, slashLastIndex + 1)}`
const parentUrl = `${origin}${ressource.slice(0, slashLastIndex + 1)}`
return parentUrl
}
import { urlToRessource } from "./urlToRessource.js"
export const urlToPathname = (urlString) => {
const ressource = urlToRessource(urlString)
export const urlToPathname = (url) => {
const ressource = urlToRessource(url)
const pathname = ressourceToPathname(ressource)

@@ -6,0 +6,0 @@ return pathname

import { getCommonPathname } from "./internal/getCommonPathname.js"
import { pathnameToParentPathname } from "./internal/pathnameToParentPathname.js"
export const urlToRelativeUrl = (urlArg, baseUrlArg) => {
const url = new URL(urlArg)
const baseUrl = new URL(baseUrlArg)
export const urlToRelativeUrl = (url, baseUrl) => {
const urlObject = new URL(url)
const baseUrlObject = new URL(baseUrl)
if (url.protocol !== baseUrl.protocol) {
return urlArg
if (urlObject.protocol !== baseUrlObject.protocol) {
const urlAsString = String(url)
return urlAsString
}
if (url.username !== baseUrl.username || url.password !== baseUrl.password) {
return urlArg.slice(url.protocol.length)
if (
urlObject.username !== baseUrlObject.username ||
urlObject.password !== baseUrlObject.password ||
urlObject.host !== baseUrlObject.host
) {
const afterUrlScheme = String(url).slice(urlObject.protocol.length)
return afterUrlScheme
}
if (url.host !== baseUrl.host) {
return urlArg.slice(url.protocol.length)
}
const { pathname, hash, search } = url
const { pathname, hash, search } = urlObject
if (pathname === "/") {
return baseUrl.pathname.slice(1)
const baseUrlRessourceWithoutLeadingSlash = baseUrlObject.pathname.slice(1)
return baseUrlRessourceWithoutLeadingSlash
}
const { pathname: basePathname } = baseUrl
const basePathname = baseUrlObject.pathname
const commonPathname = getCommonPathname(pathname, basePathname)
if (!commonPathname) {
return urlArg
const urlAsString = String(url)
return urlAsString
}

@@ -37,5 +40,8 @@

const relativeDirectoriesNotation = baseSpecificParentPathname.replace(/.*?\//g, "../")
return `${relativeDirectoriesNotation}${specificPathname}${search}${hash}`
const relativeUrl = `${relativeDirectoriesNotation}${specificPathname}${search}${hash}`
return relativeUrl
}
return `${specificPathname}${search}${hash}`
const relativeUrl = `${specificPathname}${search}${hash}`
return relativeUrl
}
import { urlToScheme } from "./urlToScheme.js"
export const urlToRessource = (urlString) => {
const scheme = urlToScheme(urlString)
export const urlToRessource = (url) => {
const scheme = urlToScheme(url)
if (scheme === "file") {
return urlString.slice("file://".length)
const urlAsStringWithoutFileProtocol = String(url).slice("file://".length)
return urlAsStringWithoutFileProtocol
}

@@ -12,8 +13,10 @@

// remove origin
const afterProtocol = urlString.slice(scheme.length + "://".length)
const afterProtocol = String(url).slice(scheme.length + "://".length)
const pathnameSlashIndex = afterProtocol.indexOf("/", "://".length)
return afterProtocol.slice(pathnameSlashIndex)
const urlAsStringWithoutOrigin = afterProtocol.slice(pathnameSlashIndex)
return urlAsStringWithoutOrigin
}
return urlString.slice(scheme.length + 1)
const urlAsStringWithoutProtocol = String(url).slice(scheme.length + 1)
return urlAsStringWithoutProtocol
}

@@ -1,2 +0,3 @@

export const urlToScheme = (urlString) => {
export const urlToScheme = (url) => {
const urlString = String(url)
const colonIndex = urlString.indexOf(":")

@@ -3,0 +4,0 @@ if (colonIndex === -1) {

@@ -1,2 +0,3 @@

import { promises } from "fs"
import { promises } from "node:fs"
import { assertAndNormalizeFileUrl } from "./assertAndNormalizeFileUrl.js"

@@ -13,24 +14,24 @@ import { urlToFileSystemPath } from "./urlToFileSystemPath.js"

export const writeSymbolicLink = async (destination, target, { type } = {}) => {
const destinationUrl = assertAndNormalizeFileUrl(destination)
export const writeSymbolicLink = async ({ from, to, type }) => {
const fromUrl = assertAndNormalizeFileUrl(from)
let targetValue
if (typeof target === "string") {
let toValue
if (typeof to === "string") {
// absolute filesystem path
if (isFileSystemPath(target)) {
targetValue = target
if (isFileSystemPath(to)) {
toValue = to
}
// relative url
else if (target.startsWith("./") || target.startsWith("../")) {
targetValue = target
else if (to.startsWith("./") || to.startsWith("../")) {
toValue = to
}
// absolute url
else {
const targetUrl = String(new URL(target, destinationUrl))
targetValue = urlToFileSystemPath(targetUrl)
const toUrl = String(new URL(to, fromUrl))
toValue = urlToFileSystemPath(toUrl)
}
} else if (target instanceof URL) {
targetValue = urlToFileSystemPath(target)
} else if (to instanceof URL) {
toValue = urlToFileSystemPath(to)
} else {
throw new TypeError(`symbolic link target must be a string or an url, received ${target}`)
throw new TypeError(`symbolic link to must be a string or an url, received ${to}`)
}

@@ -41,14 +42,14 @@

// you later get EPERM when doing stat on the symlink
const targetUrl = resolveUrl(targetValue, destinationUrl)
const targetStats = await readFileSystemNodeStat(targetUrl, { nullIfNotFound: true })
type = targetStats && targetStats.isDirectory() ? "dir" : "file"
const toUrl = resolveUrl(toValue, fromUrl)
const toStats = await readFileSystemNodeStat(toUrl, { nullIfNotFound: true })
type = toStats && toStats.isDirectory() ? "dir" : "file"
}
const symbolicLinkPath = urlToFileSystemPath(destinationUrl)
const symbolicLinkPath = urlToFileSystemPath(fromUrl)
try {
await symlink(targetValue, symbolicLinkPath, type)
await symlink(toValue, symbolicLinkPath, type)
} catch (error) {
if (error.code === "ENOENT") {
await ensureParentDirectories(destinationUrl)
await symlink(targetValue, symbolicLinkPath, type)
await ensureParentDirectories(fromUrl)
await symlink(toValue, symbolicLinkPath, type)
return

@@ -55,0 +56,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc