From f4560b3e124c1720bdfdf3c6800f66ab855f8b95 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 22 Dec 2021 18:29:00 -0500 Subject: [PATCH] feat: add `@deno/shim-prompts` package (#67) --- README.md | 4 ++ package-lock.json | 42 ++++++++++++++++++- package.json | 1 + packages/deno.ns/README.md | 3 -- packages/deno.ns/lib/deno.ns.lib.d.ts | 36 +++++----------- packages/deno.ns/package.json | 2 +- packages/deno.ns/src/index.ts | 1 - packages/deno.ns/src/util/mod.test.ts | 14 ------- packages/deno.ns/src/util/mod.ts | 35 ---------------- .../deno.ns/tools/generateDeclarationFile.ts | 2 +- packages/shim-prompts/LICENSE | 20 +++++++++ packages/shim-prompts/README.md | 3 ++ packages/shim-prompts/package.json | 35 ++++++++++++++++ packages/shim-prompts/src/index.ts | 42 +++++++++++++++++++ .../util => shim-prompts/src}/readlineSync.ts | 8 ++-- packages/shim-prompts/tsconfig.json | 18 ++++++++ packages/shim-timers/package.json | 5 ++- packages/shim-timers/src/index.test.ts | 12 ++++++ packages/shim-timers/tsconfig.json | 5 +-- 19 files changed, 197 insertions(+), 91 deletions(-) delete mode 100644 packages/deno.ns/src/util/mod.test.ts delete mode 100644 packages/deno.ns/src/util/mod.ts create mode 100644 packages/shim-prompts/LICENSE create mode 100644 packages/shim-prompts/README.md create mode 100644 packages/shim-prompts/package.json create mode 100644 packages/shim-prompts/src/index.ts rename packages/{deno.ns/src/util => shim-prompts/src}/readlineSync.ts (78%) create mode 100644 packages/shim-prompts/tsconfig.json create mode 100644 packages/shim-timers/src/index.test.ts diff --git a/README.md b/README.md index ebcd227..92fe96d 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,7 @@ Deno shims for Node.js ## Packages - [deno.ns](packages/deno.ns) - Deno namespace shim. +- [@deno/shim-prompts](packages/shim-prompts) - Shims for `alert`, `confirm` and + `prompt`. +- [@deno/shim-timers](packages/shim-timers) - Shims for `setTimeout` and + `setInterval`. diff --git a/package-lock.json b/package-lock.json index 277b7d4..431b255 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,9 @@ "": { "name": "deno.ns-workspace", "workspaces": [ - "packages/deno.ns" + "packages/deno.ns", + "packages/shim-prompts", + "packages/shim-timers" ] }, "node_modules/@cspotcode/source-map-consumer": { @@ -30,6 +32,14 @@ "node": ">=12" } }, + "node_modules/@deno/shim-prompts": { + "resolved": "packages/shim-prompts", + "link": true + }, + "node_modules/@deno/shim-timers": { + "resolved": "packages/shim-timers", + "link": true + }, "node_modules/@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", @@ -224,6 +234,22 @@ "engines": { "node": ">=16.7.0" } + }, + "packages/shim-prompts": { + "version": "0.1.0", + "license": "MIT", + "devDependencies": { + "@types/node": "^16.4.13", + "typescript": "^4.5.2" + } + }, + "packages/shim-timers": { + "version": "0.1.0", + "license": "MIT", + "devDependencies": { + "ts-node": "^10.4.0", + "typescript": "^4.5.2" + } } }, "dependencies": { @@ -242,6 +268,20 @@ "@cspotcode/source-map-consumer": "0.8.0" } }, + "@deno/shim-prompts": { + "version": "file:packages/shim-prompts", + "requires": { + "@types/node": "^16.4.13", + "typescript": "^4.5.2" + } + }, + "@deno/shim-timers": { + "version": "file:packages/shim-timers", + "requires": { + "ts-node": "^10.4.0", + "typescript": "^4.5.2" + } + }, "@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", diff --git a/package.json b/package.json index 08a3ab9..2150d52 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "deno.ns-workspace", "workspaces": [ "packages/deno.ns", + "packages/shim-prompts", "packages/shim-timers" ], "scripts": { diff --git a/packages/deno.ns/README.md b/packages/deno.ns/README.md index 35c3cea..20ed47d 100644 --- a/packages/deno.ns/README.md +++ b/packages/deno.ns/README.md @@ -9,16 +9,13 @@ See ```js const { - alert, Blob, - confirm, crypto, Deno, fetch, File, FormData, Headers, - prompt, Request, Response, } = require("deno.ns"); diff --git a/packages/deno.ns/lib/deno.ns.lib.d.ts b/packages/deno.ns/lib/deno.ns.lib.d.ts index bd00c8f..de8fdd7 100644 --- a/packages/deno.ns/lib/deno.ns.lib.d.ts +++ b/packages/deno.ns/lib/deno.ns.lib.d.ts @@ -184,31 +184,6 @@ export declare type Request = GlobalThisPrototypeType<"Request", undici.Request> export declare const Request: GlobalThisType<"Request", typeof undici.Request>; export declare type Response = GlobalThisPrototypeType<"Response", undici.Response>; export declare const Response: GlobalThisType<"Response", typeof undici.Response>; -export declare function setTimeout(cb: (...args: any[]) => void, delay?: number, ...args: any[]): number; -export declare function setInterval(cb: (...args: any[]) => void, delay?: number, ...args: any[]): number; -/** - * Shows the given message and waits for the enter key pressed. - * If the stdin is not interactive, it does nothing. - * @param message - */ -export declare function alert(message?: string): void; -/** - * Shows the given message and waits for the answer. Returns the user's answer as boolean. - * Only `y` and `Y` are considered as true. - * If the stdin is not interactive, it returns false. - * @param message - */ -export declare function confirm(message?: string): boolean; -/** - * Shows the given message and waits for the user's input. Returns the user's input as string. - * If the default value is given and the user inputs the empty string, then it returns the given - * default value. - * If the default value is not given and the user inputs the empty string, it returns null. - * If the stdin is not interactive, it returns null. - * @param message - * @param defaultValue - */ -export declare function prompt(message?: string, defaultValue?: string): string | null; export declare namespace Deno { export class File implements Deno.File { @@ -2819,6 +2794,17 @@ export declare namespace Deno { * Requires `allow-write` permission. */ export function utimeSync(path: string | URL, atime: number | Date, mtime: number | Date): void; + /** + * UNSTABLE**: new API, yet to be vetted. + * + * SleepSync puts the main thread to sleep synchronously for a given amount of + * time in milliseconds. + * + * ```ts + * Deno.sleepSync(10); + * ``` + */ + export function sleepSync(millis: number): void; } declare module "deno.ns/deno" { diff --git a/packages/deno.ns/package.json b/packages/deno.ns/package.json index 2371339..46db9eb 100644 --- a/packages/deno.ns/package.json +++ b/packages/deno.ns/package.json @@ -37,7 +37,7 @@ "clean": "git clean -fXde !node_modules/", "test": "node --loader=ts-node/esm tools/run_tests.mjs", "denolib": "deno run --allow-run --allow-write=src/deno tools/denolib.ts", - "generate-declaration-file": "deno run --allow-write=lib --allow-read=. ctools/generateDeclarationFile.ts", + "generate-declaration-file": "deno run --allow-write=lib --allow-read=. tools/generateDeclarationFile.ts", "update-progress": "deno run --allow-read tools/missing.ts > PROGRESS.md" }, "engines": { diff --git a/packages/deno.ns/src/index.ts b/packages/deno.ns/src/index.ts index b14fc25..740fad1 100644 --- a/packages/deno.ns/src/index.ts +++ b/packages/deno.ns/src/index.ts @@ -1,6 +1,5 @@ export { webcrypto as crypto } from "crypto"; export * as Deno from "./deno.js"; -export * from "./util/mod.js"; // TODO: Wait for node builtin WhatWG Streams or fetch-blob to export them without assigning to globalThis import * as undici from "undici"; diff --git a/packages/deno.ns/src/util/mod.test.ts b/packages/deno.ns/src/util/mod.test.ts deleted file mode 100644 index 64bd1c6..0000000 --- a/packages/deno.ns/src/util/mod.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { setInterval, setTimeout } from "./mod.js"; -import assert from "assert/strict"; - -Deno.test("should get setTimeout result that's a number", () => { - const timeoutId = setTimeout(() => {}, 100); - assert.equal("number", typeof timeoutId); - clearTimeout(timeoutId); -}); - -Deno.test("should get setInterval result that's a number", () => { - const intervalId = setInterval(() => {}, 100); - assert.equal("number", typeof intervalId); - clearInterval(intervalId); -}); diff --git a/packages/deno.ns/src/util/mod.ts b/packages/deno.ns/src/util/mod.ts deleted file mode 100644 index 2413bae..0000000 --- a/packages/deno.ns/src/util/mod.ts +++ /dev/null @@ -1,35 +0,0 @@ -/// - -import { writeSync } from "fs"; -import { readlineSync } from "./readlineSync.js"; - -export const alert: typeof globalThis.alert = globalThis["alert"] ?? - function alert(message) { - writeSync( - process.stdout.fd, - new TextEncoder().encode(`${message} [Enter] `), - ); - readlineSync(); - }; - -export const confirm: typeof globalThis.confirm = globalThis["confirm"] ?? - function confirm(message) { - writeSync(process.stdout.fd, new TextEncoder().encode(`${message} [y/N] `)); - const result = readlineSync(); - return ["y", "Y"].includes(result); - }; - -export const prompt: typeof globalThis.prompt = globalThis["prompt"] ?? - function prompt( - message, - defaultValue = undefined, - ) { - writeSync( - process.stdout.fd, - new TextEncoder().encode( - `${message} ${defaultValue == null ? "" : `[${defaultValue}]`} `, - ), - ); - const result = readlineSync(); - return result.length > 0 ? result : defaultValue ?? null; - }; diff --git a/packages/deno.ns/tools/generateDeclarationFile.ts b/packages/deno.ns/tools/generateDeclarationFile.ts index 0de7387..fba0c55 100644 --- a/packages/deno.ns/tools/generateDeclarationFile.ts +++ b/packages/deno.ns/tools/generateDeclarationFile.ts @@ -283,7 +283,7 @@ function getDeclarationProject() { tsConfigFilePath: `./tsconfig.json`, }); - // exitIfDiagnostics(project, project.getPreEmitDiagnostics()); + exitIfDiagnostics(project, project.getPreEmitDiagnostics()); const dtsEmitResult = project.emitToMemory({ emitOnlyDtsFiles: true, diff --git a/packages/shim-prompts/LICENSE b/packages/shim-prompts/LICENSE new file mode 100644 index 0000000..310d4c6 --- /dev/null +++ b/packages/shim-prompts/LICENSE @@ -0,0 +1,20 @@ +MIT License + +Copyright 2021 the Deno authors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/shim-prompts/README.md b/packages/shim-prompts/README.md new file mode 100644 index 0000000..63d754e --- /dev/null +++ b/packages/shim-prompts/README.md @@ -0,0 +1,3 @@ +# @deno/shim-prompts + +Shims for `alert`, `confirm`, and `prompt` that work in Node.js. diff --git a/packages/shim-prompts/package.json b/packages/shim-prompts/package.json new file mode 100644 index 0000000..7534800 --- /dev/null +++ b/packages/shim-prompts/package.json @@ -0,0 +1,35 @@ +{ + "name": "@deno/shim-prompts", + "version": "0.1.0", + "description": "alert, confirm, and prompt for Node.js", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "prepare": "echo \"Prepared.\"", + "build": "tsc", + "test": "echo \"No tests yet\"" + }, + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/denoland/deno.ns.git" + }, + "keywords": [ + "shim", + "deno", + "node.js", + "prompts" + ], + "author": "The Deno authors", + "license": "MIT", + "bugs": { + "url": "https://github.com/denoland/deno.ns/issues" + }, + "homepage": "https://github.com/denoland/deno.ns#readme", + "devDependencies": { + "@types/node": "^16.4.13", + "typescript": "^4.5.2" + } +} diff --git a/packages/shim-prompts/src/index.ts b/packages/shim-prompts/src/index.ts new file mode 100644 index 0000000..cdd4228 --- /dev/null +++ b/packages/shim-prompts/src/index.ts @@ -0,0 +1,42 @@ +import { writeSync } from "fs"; +import { readlineSync } from "./readlineSync.js"; + +export const alert: (typeof globalThis) extends { [P in "alert"]: infer T } ? T + : (message?: any) => void = (globalThis as any)["alert"] ?? + function alert(message) { + writeSync( + process.stdout.fd, + new TextEncoder().encode(`${message} [Enter] `), + ); + readlineSync(); + }; + +export const confirm: (typeof globalThis) extends { [P in "confirm"]: infer T } + ? T + : (message?: string) => boolean = (globalThis as any)["confirm"] ?? + function confirm(message) { + writeSync( + process.stdout.fd, + new TextEncoder().encode(`${message} [y/N] `), + ); + const result = readlineSync(); + return ["y", "Y"].includes(result); + }; + +export const prompt: (typeof globalThis) extends { [P in "prompt"]: infer T } + ? T + : (message?: string, _default?: string) => string | null = + (globalThis as any)["prompt"] ?? + function prompt( + message, + defaultValue = undefined, + ) { + writeSync( + process.stdout.fd, + new TextEncoder().encode( + `${message} ${defaultValue == null ? "" : `[${defaultValue}]`} `, + ), + ); + const result = readlineSync(); + return result.length > 0 ? result : defaultValue ?? null; + }; diff --git a/packages/deno.ns/src/util/readlineSync.ts b/packages/shim-prompts/src/readlineSync.ts similarity index 78% rename from packages/deno.ns/src/util/readlineSync.ts rename to packages/shim-prompts/src/readlineSync.ts index 2ea1c87..1a183e9 100644 --- a/packages/deno.ns/src/util/readlineSync.ts +++ b/packages/shim-prompts/src/readlineSync.ts @@ -1,5 +1,6 @@ import { readSync } from "fs"; -export const readlineSync = () => { + +export function readlineSync() { let line = ""; let char = ""; const buf = Buffer.alloc(1); @@ -10,8 +11,7 @@ export const readlineSync = () => { if (bytesRead === 0) { return line; } - } catch (err) { - // @ts-expect-error Property 'code' does not exist on type 'Error'. + } catch (err: any) { if (err.code === "EOF") { return line; } @@ -23,4 +23,4 @@ export const readlineSync = () => { readSync(process.stdin.fd, buf, 0, 1, 0); } return line; -}; +} diff --git a/packages/shim-prompts/tsconfig.json b/packages/shim-prompts/tsconfig.json new file mode 100644 index 0000000..ef76ba2 --- /dev/null +++ b/packages/shim-prompts/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "strict": true, + "target": "ES2019", + "declaration": true, + "outDir": "dist", + "stripInternal": true + }, + "ts-node": { + "transpileOnly": true, + "files": true, + "compilerOptions": { + "module": "ES2015" + } + }, + "files": ["src/index.ts"] +} diff --git a/packages/shim-timers/package.json b/packages/shim-timers/package.json index 08a2c78..bcd58c5 100644 --- a/packages/shim-timers/package.json +++ b/packages/shim-timers/package.json @@ -7,7 +7,7 @@ "scripts": { "prepare": "echo \"Prepared.\"", "build": "tsc", - "test": "echo \"No tests yet\"" + "test": "ts-node --project tsconfig.json src/index.test.ts" }, "files": [ "dist" @@ -29,6 +29,7 @@ }, "homepage": "https://github.com/denoland/deno.ns#readme", "devDependencies": { - "typescript": "^4.5.2" + "typescript": "^4.5.2", + "ts-node": "^10.4.0" } } diff --git a/packages/shim-timers/src/index.test.ts b/packages/shim-timers/src/index.test.ts new file mode 100644 index 0000000..9b96db2 --- /dev/null +++ b/packages/shim-timers/src/index.test.ts @@ -0,0 +1,12 @@ +import { setInterval, setTimeout } from "./index"; +import * as assert from "assert/strict"; + +console.log("should get setTimeout result that's a number..."); +const timeoutId = setTimeout(() => {}, 100); +assert.equal("number", typeof timeoutId); +clearTimeout(timeoutId); + +console.log("should get setInterval result that's a number"); +const intervalId = setInterval(() => {}, 100); +assert.equal("number", typeof intervalId); +clearInterval(intervalId); diff --git a/packages/shim-timers/tsconfig.json b/packages/shim-timers/tsconfig.json index 6e52a4c..5965261 100644 --- a/packages/shim-timers/tsconfig.json +++ b/packages/shim-timers/tsconfig.json @@ -10,10 +10,7 @@ }, "ts-node": { "transpileOnly": true, - "files": true, - "compilerOptions": { - "module": "ES2015" - } + "files": true }, "files": ["src/index.ts"] }