Skip to content

Commit

Permalink
feat(run)!: support deno 2
Browse files Browse the repository at this point in the history
  • Loading branch information
lowlighter committed Sep 28, 2024
1 parent 6f03167 commit bbb7d84
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 84 deletions.
4 changes: 4 additions & 0 deletions run/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ console.assert(stdout.includes("hello"))
- Optionally decide to throw an error when the process exits with a non-zero code.
- Generates a `stdio` history that contains timestamped entries with configurable buffering

## 🕊️ Migrating from `2.x.x` to `3.x.x`

Version `3.x.x` and onwards require Deno `2.x.x` or later.

## 📜 Licenses

```plaintext
Expand Down
22 changes: 11 additions & 11 deletions run/command_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Logger } from "@libs/logger"
import { command } from "./command.ts"
import { expect, test, type testing } from "@libs/testing"

test("deno")("command() can spawn subprocesses asynchronously", async () => {
test("deno")("`command()` can spawn subprocesses asynchronously", async () => {
let result = command("deno", ["--version"], { env: { NO_COLOR: "true" } }) as testing
expect(result).toBeInstanceOf(Promise)
result = await result
Expand All @@ -11,21 +11,21 @@ test("deno")("command() can spawn subprocesses asynchronously", async () => {
expect(result.stdout).toMatch(/deno/)
}, { permissions: { run: ["deno"] } })

test("deno")("command() can spawn subprocesses synchronously", () => {
test("deno")("`command()` can spawn subprocesses synchronously", () => {
const result = command("deno", ["--version"], { env: { NO_COLOR: "true" }, sync: true })
expect(result).not.toBeInstanceOf(Promise)
expect(result).toMatchObject({ success: true, code: 0, stdin: "", stderr: "" })
expect(result.stdio).toBeInstanceOf(Array)
expect(result.stdout).toMatch(/deno/)
}, { permissions: { run: ["deno"] } })

test("deno")("command() handles callback<write()> and callback<close()> calls", async () => {
test("deno")("`command()` handles `callback<write()>` and `callback<close()>` calls", async () => {
const result = await command("deno", ["repl"], { stdin: "debug", env: { NO_COLOR: "true" }, callback: ({ i, write, close }) => i === 0 ? write("console.log('hello')") : close() })
expect(result).toMatchObject({ success: true, code: 0, stdin: "console.log('hello')" })
expect(result.stdout).toMatch(/hello/)
}, { permissions: { run: ["deno"] } })

test("deno")("command() handles multiple callback<close()> calls", async () => {
test("deno")("`command()` handles multiple `callback<close()>` calls", async () => {
const result = await command("deno", ["repl"], {
env: { NO_COLOR: "true" },
callback: async ({ close }) => {
Expand All @@ -36,7 +36,7 @@ test("deno")("command() handles multiple callback<close()> calls", async () => {
expect(result).toMatchObject({ success: true, code: 0 })
}, { permissions: { run: ["deno"] } })

test("deno")("command() handles callback<wait()> calls", async () => {
test("deno")("`command()` handles `callback<wait()>` calls", async () => {
let waited = false
const result = await command("deno", ["repl"], {
env: { NO_COLOR: "true" },
Expand All @@ -47,7 +47,7 @@ test("deno")("command() handles callback<wait()> calls", async () => {

for (const sync of [false, true]) {
for (const mode of ["inherit", "piped", null, "debug", "log", "info", "warn", "error"] as const) {
test("deno")(`command() supports stdio set to "${mode}" in "${sync ? "sync" : "async"}" mode`, async () => {
test("deno")(`\`command()\` supports stdio set to \`"${mode}"\` in ${sync ? "sync" : "async"} mode`, async () => {
const result = await command("deno", ["eval", "null"], {
logger: new Logger({ level: "disabled" }),
env: { NO_COLOR: "true" },
Expand All @@ -61,7 +61,7 @@ for (const sync of [false, true]) {
}
}

test("deno")("command() handles both stdout and stderr channels", async () => {
test("deno")("`command()` handles both stdout and stderr channels", async () => {
const result = await command("deno", ["eval", "await Deno.stdout.write(new TextEncoder().encode(`foo\n`));await Deno.stderr.write(new TextEncoder().encode(`bar\n`))"], {
env: { NO_COLOR: "true" },
stdout: "piped",
Expand All @@ -70,7 +70,7 @@ test("deno")("command() handles both stdout and stderr channels", async () => {
expect(result).toMatchObject({ success: true, code: 0, stdout: "foo", stderr: "bar" })
}, { permissions: { run: ["deno"] } })

test("deno")("command() supports buffering", async () => {
test("deno")("`command()` supports buffering", async () => {
// Combined entries if buffering is greater than the time between writes
{
const result = await command("deno", ["eval", "console.log(`foo`);await new Promise(resolve => setTimeout(resolve, 100));console.log(`bar`)"], {
Expand Down Expand Up @@ -112,16 +112,16 @@ test("deno")("command() supports buffering", async () => {
}
}, { permissions: { run: ["deno"] } })

test("deno")("command() throws an error when `throw` option is enabled and exit code is non-zero", async () => {
test("deno")("`command()` throws an error when throw option is enabled and exit code is non-zero", async () => {
expect(() => command("deno", ["eval", "Deno.exit(1)"], { env: { NO_COLOR: "true" }, throw: true, sync: true })).toThrow(EvalError)
await expect(command("deno", ["eval", "Deno.exit(1)"], { env: { NO_COLOR: "true" }, throw: true })).rejects.toThrow(EvalError)
}, { permissions: { run: ["deno"] } })

test("deno")("command() does nothing in dryrun", async () => {
test("deno")("`command()` does nothing in dryrun", async () => {
expect(command("deno", ["--version"], { dryrun: true, sync: true })).toMatchObject({ success: true, code: 0, stdio: [], stdin: "", stderr: "", stdout: "" })
await expect(command("deno", ["--version"], { dryrun: true })).resolves.toMatchObject({ success: true, code: 0, stdio: [], stdin: "", stderr: "", stdout: "" })
}, { permissions: { run: ["deno"] } })

test("deno")("command() appends windows extension when os platform is windows", () => {
test("deno")("`command()` appends windows extension when os platform is windows", () => {
expect(command("", ["--version"], { logger: new Logger({ level: "disabled" }), sync: true, winext: "deno", os: "windows" })).toMatchObject({ success: true, code: 0 })
}, { permissions: { run: ["deno"] } })
14 changes: 7 additions & 7 deletions run/deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
"@std/async/delay": "jsr:@std/async@1/delay",
"@std/async/debounce": "jsr:@std/async@1/debounce",
"@std/streams": "jsr:@std/streams@1",
"@libs/logger": "jsr:@libs/logger@2",
"@libs/testing": "jsr:@libs/testing@2",
"@libs/typing": "jsr:@libs/typing@2"
"@libs/logger": "jsr:@libs/logger@3",
"@libs/testing": "jsr:@libs/testing@3",
"@libs/typing": "jsr:@libs/typing@3"
},
"test:permissions": {
"run": [
Expand All @@ -42,11 +42,11 @@
},
"tasks": {
"test": "deno test --allow-run=deno,node,bun,npx --no-prompt --coverage --clean --trace-leaks --doc",
"dev": "deno fmt && deno task test --filter='/^\\[deno\\]/' && deno coverage --exclude=.js --detailed && deno task lint",
"test:deno": "deno task clean:deno && deno fmt --check && deno task test --filter='/^\\[deno\\]/' --quiet && deno coverage --exclude=.js && deno lint",
"dev": "deno fmt && deno task test --filter='/DENO/' && deno coverage --exclude=.js --detailed && deno task lint",
"test:deno": "deno task clean:deno && deno fmt --check && deno task test --filter='/DENO/' --quiet && deno coverage --exclude=.js && deno lint",
"test:deno-future": "deno task clean:deno && DENO_FUTURE=1 && deno task test:deno",
"test:others": "deno task clean:others && deno fmt --check && deno task test --filter='/^\\[node|bun \\]/' --quiet && deno coverage --exclude=.js && deno lint",
"coverage:html": "deno task test --filter='/^\\[deno\\]/' --quiet && deno coverage --exclude=.js --html && sleep 1",
"test:others": "deno task clean:others && deno fmt --check && deno task test --filter='/NODE|BUN/' --quiet && deno coverage --exclude=.js && deno lint",
"coverage:html": "deno task test --filter='/DENO/' --quiet && deno coverage --exclude=.js --html && sleep 1",
"lint": "deno fmt --check && deno lint && deno doc --lint mod.ts && deno publish --dry-run --quiet --allow-dirty",
"clean:deno": "rm -rf node_modules .npmrc deno.lock",
"clean:others": "rm -rf node_modules .npmrc deno.lock package.json package-lock.json bun.lockb"
Expand Down
150 changes: 84 additions & 66 deletions run/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bbb7d84

Please sign in to comment.