From 5cc0f056d1af6f76c6ad81a6cd68dcaabba60f35 Mon Sep 17 00:00:00 2001 From: Ali Hasani Date: Sun, 3 May 2020 23:44:38 +0430 Subject: [PATCH] [std/node] add the ability to path argument to be URL type (#5055) --- std/node/_fs/_fs_access.ts | 8 ++++---- std/node/_fs/_fs_appendFile.ts | 13 ++++++++----- std/node/_fs/_fs_appendFile_test.ts | 26 ++++++++++++++++++++++++++ std/node/_fs/_fs_chmod.ts | 12 ++++++++---- std/node/_fs/_fs_chown.ts | 13 +++++++++---- std/node/_fs/_fs_copy.ts | 8 ++++++-- std/node/_fs/_fs_exists.ts | 9 ++++++--- std/node/_fs/_fs_mkdir.ts | 11 +++++++---- std/node/_fs/_fs_readFile.ts | 7 +++++-- std/node/_fs/_fs_readlink.ts | 9 +++++++-- 10 files changed, 86 insertions(+), 30 deletions(-) diff --git a/std/node/_fs/_fs_access.ts b/std/node/_fs/_fs_access.ts index a8cec14dbd..ee93c4c7f0 100644 --- a/std/node/_fs/_fs_access.ts +++ b/std/node/_fs/_fs_access.ts @@ -5,19 +5,19 @@ import { notImplemented } from "../_utils.ts"; /** Revist once https://github.com/denoland/deno/issues/4017 lands */ -//TODO - 'path' can also be a Buffer or URL. Neither of these polyfills +//TODO - 'path' can also be a Buffer. Neither of these polyfills //is available yet. See https://github.com/denoland/deno/issues/3403 export function access( - path: string, // eslint-disable-line @typescript-eslint/no-unused-vars + path: string | URL, // eslint-disable-line @typescript-eslint/no-unused-vars modeOrCallback: number | Function, // eslint-disable-line @typescript-eslint/no-unused-vars callback?: CallbackWithError // eslint-disable-line @typescript-eslint/no-unused-vars ): void { notImplemented("Not yet available"); } -//TODO - 'path' can also be a Buffer or URL. Neither of these polyfills +//TODO - 'path' can also be a Buffer. Neither of these polyfills //is available yet. See https://github.com/denoland/deno/issues/3403 // eslint-disable-next-line @typescript-eslint/no-unused-vars -export function accessSync(path: string, mode?: number): void { +export function accessSync(path: string | URL, mode?: number): void { notImplemented("Not yet available"); } diff --git a/std/node/_fs/_fs_appendFile.ts b/std/node/_fs/_fs_appendFile.ts index 48b05ff805..b116589a0f 100644 --- a/std/node/_fs/_fs_appendFile.ts +++ b/std/node/_fs/_fs_appendFile.ts @@ -1,17 +1,19 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { FileOptions, isFileOptions, CallbackWithError } from "./_fs_common.ts"; import { notImplemented } from "../_utils.ts"; +import { fromFileUrl } from "../path.ts"; /** - * TODO: Also accept 'data' parameter as a Node polyfill Buffer or URL type once these + * TODO: Also accept 'data' parameter as a Node polyfill Buffer type once these * are implemented. See https://github.com/denoland/deno/issues/3403 */ export function appendFile( - pathOrRid: string | number, + pathOrRid: string | number | URL, data: string, optionsOrCallback: string | FileOptions | CallbackWithError, callback?: CallbackWithError ): void { + pathOrRid = pathOrRid instanceof URL ? fromFileUrl(pathOrRid) : pathOrRid; const callbackFn: CallbackWithError | undefined = optionsOrCallback instanceof Function ? optionsOrCallback : callback; const options: string | FileOptions | undefined = @@ -39,7 +41,7 @@ export function appendFile( //TODO rework once https://github.com/denoland/deno/issues/4017 completes notImplemented("Deno does not yet support setting mode on create"); } - Deno.open(pathOrRid, getOpenOptions(flag)) + Deno.open(pathOrRid as string, getOpenOptions(flag)) .then(({ rid: openedFileRid }) => { rid = openedFileRid; return Deno.write(openedFileRid, buffer); @@ -66,17 +68,18 @@ function closeRidIfNecessary(isPathString: boolean, rid: number): void { } /** - * TODO: Also accept 'data' parameter as a Node polyfill Buffer or URL type once these + * TODO: Also accept 'data' parameter as a Node polyfill Buffer type once these * are implemented. See https://github.com/denoland/deno/issues/3403 */ export function appendFileSync( - pathOrRid: string | number, + pathOrRid: string | number | URL, data: string, options?: string | FileOptions ): void { let rid = -1; validateEncoding(options); + pathOrRid = pathOrRid instanceof URL ? fromFileUrl(pathOrRid) : pathOrRid; try { if (typeof pathOrRid === "number") { diff --git a/std/node/_fs/_fs_appendFile_test.ts b/std/node/_fs/_fs_appendFile_test.ts index ca48dc5d3b..402ac1c103 100644 --- a/std/node/_fs/_fs_appendFile_test.ts +++ b/std/node/_fs/_fs_appendFile_test.ts @@ -2,6 +2,7 @@ const { test } = Deno; import { assertEquals, assertThrows, fail } from "../../testing/asserts.ts"; import { appendFile, appendFileSync } from "./_fs_appendFile.ts"; +import { fromFileUrl } from "../path.ts"; const decoder = new TextDecoder("utf-8"); @@ -109,6 +110,31 @@ test({ }, }); +test({ + name: "Async: Data is written to passed in URL", + async fn() { + const openResourcesBeforeAppend: Deno.ResourceMap = Deno.resources(); + const fileURL = new URL("_fs_appendFile_test_file.txt", import.meta.url); + await new Promise((resolve, reject) => { + appendFile(fileURL, "hello world", (err) => { + if (err) reject(err); + else resolve(); + }); + }) + .then(async () => { + assertEquals(Deno.resources(), openResourcesBeforeAppend); + const data = await Deno.readFile(fromFileUrl(fileURL)); + assertEquals(decoder.decode(data), "hello world"); + }) + .catch((err) => { + fail("No error was expected: " + err); + }) + .finally(async () => { + await Deno.remove(fromFileUrl(fileURL)); + }); + }, +}); + test({ name: "Async: Callback is made with error if attempting to append data to an existing file with 'ax' flag", diff --git a/std/node/_fs/_fs_chmod.ts b/std/node/_fs/_fs_chmod.ts index 2adff59ffb..b1079e0a14 100644 --- a/std/node/_fs/_fs_chmod.ts +++ b/std/node/_fs/_fs_chmod.ts @@ -1,28 +1,32 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { CallbackWithError } from "./_fs_common.ts"; +import { fromFileUrl } from "../path.ts"; const allowedModes = /^[0-7]{3}/; /** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these + * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these * are implemented. See https://github.com/denoland/deno/issues/3403 */ export function chmod( - path: string, + path: string | URL, mode: string | number, callback: CallbackWithError ): void { + path = path instanceof URL ? fromFileUrl(path) : path; + Deno.chmod(path, getResolvedMode(mode)) .then(() => callback()) .catch(callback); } /** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these + * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these * are implemented. See https://github.com/denoland/deno/issues/3403 */ -export function chmodSync(path: string, mode: string | number): void { +export function chmodSync(path: string | URL, mode: string | number): void { + path = path instanceof URL ? fromFileUrl(path) : path; Deno.chmodSync(path, getResolvedMode(mode)); } diff --git a/std/node/_fs/_fs_chown.ts b/std/node/_fs/_fs_chown.ts index c6baa4722b..cd1973b1f7 100644 --- a/std/node/_fs/_fs_chown.ts +++ b/std/node/_fs/_fs_chown.ts @@ -1,26 +1,31 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { CallbackWithError } from "./_fs_common.ts"; +import { fromFileUrl } from "../path.ts"; /** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these + * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these * are implemented. See https://github.com/denoland/deno/issues/3403 */ export function chown( - path: string, + path: string | URL, uid: number, gid: number, callback: CallbackWithError ): void { + path = path instanceof URL ? fromFileUrl(path) : path; + Deno.chown(path, uid, gid) .then(() => callback()) .catch(callback); } /** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these + * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these * are implemented. See https://github.com/denoland/deno/issues/3403 */ -export function chownSync(path: string, uid: number, gid: number): void { +export function chownSync(path: string | URL, uid: number, gid: number): void { + path = path instanceof URL ? fromFileUrl(path) : path; + Deno.chownSync(path, uid, gid); } diff --git a/std/node/_fs/_fs_copy.ts b/std/node/_fs/_fs_copy.ts index 0193e77c41..26d9a8c9a2 100644 --- a/std/node/_fs/_fs_copy.ts +++ b/std/node/_fs/_fs_copy.ts @@ -1,17 +1,21 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { CallbackWithError } from "./_fs_common.ts"; +import { fromFileUrl } from "../path.ts"; export function copyFile( - source: string, + source: string | URL, destination: string, callback: CallbackWithError ): void { + source = source instanceof URL ? fromFileUrl(source) : source; + Deno.copyFile(source, destination) .then(() => callback()) .catch(callback); } -export function copyFileSync(source: string, destination: string): void { +export function copyFileSync(source: string | URL, destination: string): void { + source = source instanceof URL ? fromFileUrl(source) : source; Deno.copyFileSync(source, destination); } diff --git a/std/node/_fs/_fs_exists.ts b/std/node/_fs/_fs_exists.ts index c3bea0d4ea..e6e6e4f2e6 100644 --- a/std/node/_fs/_fs_exists.ts +++ b/std/node/_fs/_fs_exists.ts @@ -1,13 +1,15 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import { fromFileUrl } from "../path.ts"; type ExitsCallback = (exists: boolean) => void; /** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these + * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these * are implemented. See https://github.com/denoland/deno/issues/3403 * Deprecated in node api */ -export function exists(path: string, callback: ExitsCallback): void { +export function exists(path: string | URL, callback: ExitsCallback): void { + path = path instanceof URL ? fromFileUrl(path) : path; Deno.lstat(path) .then(() => { callback(true); @@ -19,7 +21,8 @@ export function exists(path: string, callback: ExitsCallback): void { * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these * are implemented. See https://github.com/denoland/deno/issues/3403 */ -export function existsSync(path: string): boolean { +export function existsSync(path: string | URL): boolean { + path = path instanceof URL ? fromFileUrl(path) : path; try { Deno.lstatSync(path); return true; diff --git a/std/node/_fs/_fs_mkdir.ts b/std/node/_fs/_fs_mkdir.ts index fd2156c37d..a65db8dba3 100644 --- a/std/node/_fs/_fs_mkdir.ts +++ b/std/node/_fs/_fs_mkdir.ts @@ -1,21 +1,23 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. import { CallbackWithError } from "./_fs_common.ts"; +import { fromFileUrl } from "../path.ts"; /** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these + * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these * are implemented. See https://github.com/denoland/deno/issues/3403 */ -type Path = string; type MkdirOptions = | { recursive?: boolean; mode?: number | undefined } | number | boolean; export function mkdir( - path: Path, + path: string | URL, options?: MkdirOptions | CallbackWithError, callback?: CallbackWithError ): void { + path = path instanceof URL ? fromFileUrl(path) : path; + let mode = 0o777; let recursive = false; @@ -46,7 +48,8 @@ export function mkdir( }); } -export function mkdirSync(path: Path, options?: MkdirOptions): void { +export function mkdirSync(path: string | URL, options?: MkdirOptions): void { + path = path instanceof URL ? fromFileUrl(path) : path; let mode = 0o777; let recursive = false; diff --git a/std/node/_fs/_fs_readFile.ts b/std/node/_fs/_fs_readFile.ts index 13e82bfe1d..8d3c96db0b 100644 --- a/std/node/_fs/_fs_readFile.ts +++ b/std/node/_fs/_fs_readFile.ts @@ -5,6 +5,7 @@ import { intoCallbackAPIWithIntercept, MaybeEmpty, } from "../_utils.ts"; +import { fromFileUrl } from "../path.ts"; const { readFile: denoReadFile, readFileSync: denoReadFileSync } = Deno; @@ -51,10 +52,11 @@ function maybeDecode( } export function readFile( - path: string, + path: string | URL, optOrCallback: ReadFileCallback | ReadFileOptions, callback?: ReadFileCallback ): void { + path = path instanceof URL ? fromFileUrl(path) : path; let cb: ReadFileCallback | undefined; if (typeof optOrCallback === "function") { cb = optOrCallback; @@ -73,8 +75,9 @@ export function readFile( } export function readFileSync( - path: string, + path: string | URL, opt?: ReadFileOptions ): string | Uint8Array { + path = path instanceof URL ? fromFileUrl(path) : path; return maybeDecode(denoReadFileSync(path), getEncoding(opt)); } diff --git a/std/node/_fs/_fs_readlink.ts b/std/node/_fs/_fs_readlink.ts index b32cd9dd36..d461cf390e 100644 --- a/std/node/_fs/_fs_readlink.ts +++ b/std/node/_fs/_fs_readlink.ts @@ -4,6 +4,7 @@ import { MaybeEmpty, notImplemented, } from "../_utils.ts"; +import { fromFileUrl } from "../path.ts"; const { readLink: denoReadlink, readLinkSync: denoReadlinkSync } = Deno; @@ -49,10 +50,12 @@ function getEncoding( } export function readlink( - path: string, + path: string | URL, optOrCallback: ReadlinkCallback | ReadlinkOptions, callback?: ReadlinkCallback ): void { + path = path instanceof URL ? fromFileUrl(path) : path; + let cb: ReadlinkCallback | undefined; if (typeof optOrCallback === "function") { cb = optOrCallback; @@ -71,8 +74,10 @@ export function readlink( } export function readlinkSync( - path: string, + path: string | URL, opt?: ReadlinkOptions ): string | Uint8Array { + path = path instanceof URL ? fromFileUrl(path) : path; + return maybeEncode(denoReadlinkSync(path), getEncoding(opt)); }