Commit bf26083
Changed files (4)
src
test
src/cli.ts
@@ -26,6 +26,7 @@ import {
fetch,
fs,
path,
+ stdin,
VERSION,
} from './index.js'
import { installDeps, parseDeps } from './deps.js'
@@ -113,100 +114,95 @@ export async function main() {
await startRepl()
return
}
- if (argv.eval) {
- await runScript(argv.eval, argv.ext)
- return
- }
- const [firstArg] = argv._
- updateArgv(argv._.slice(firstArg === undefined ? 0 : 1))
- if (!firstArg || firstArg === '-') {
- const success = await scriptFromStdin(argv.ext)
- if (!success) {
- printUsage()
- process.exitCode = 1
- }
- return
- }
- if (/^https?:/.test(firstArg)) {
- await scriptFromHttp(firstArg, argv.ext)
- return
- }
- const filepath = firstArg.startsWith('file:')
- ? url.fileURLToPath(firstArg)
- : path.resolve(firstArg)
- await importPath(filepath)
-}
-export async function runScript(script: string, ext?: string) {
- const filepath = getFilepath($.cwd, 'zx', ext)
- await writeAndImport(script, filepath)
+ const { script, scriptPath, tempPath } = await readScript()
+ await runScript(script, scriptPath, tempPath)
}
-export async function scriptFromStdin(ext?: string): Promise<boolean> {
- let script = ''
- if (!process.stdin.isTTY) {
- process.stdin.setEncoding('utf8')
- for await (const chunk of process.stdin) {
- script += chunk
+async function runScript(
+ script: string,
+ scriptPath: string,
+ tempPath: string
+): Promise<void> {
+ const rmTemp = () => fs.rmSync(tempPath, { force: true })
+ try {
+ if (tempPath) {
+ scriptPath = tempPath
+ await fs.writeFile(tempPath, script)
}
- if (script.length > 0) {
- await runScript(script, ext)
- return true
+ if (argv.install) {
+ await installDeps(
+ parseDeps(script),
+ path.dirname(scriptPath),
+ argv.registry
+ )
}
- }
- return false
-}
-export async function scriptFromHttp(remote: string, _ext?: string) {
- const res = await fetch(remote)
- if (!res.ok) {
- console.error(`Error: Can't get ${remote}`)
- process.exit(1)
- }
- const script = await res.text()
- const pathname = new URL(remote).pathname
- const { name, ext } = path.parse(pathname)
- const filepath = getFilepath($.cwd, name, _ext || ext)
- await writeAndImport(script, filepath)
-}
+ injectGlobalRequire(scriptPath)
+ process.once('exit', rmTemp)
-export async function writeAndImport(
- script: string | Buffer,
- filepath: string,
- origin = filepath
-) {
- await fs.writeFile(filepath, script)
- try {
- process.once('exit', () => fs.rmSync(filepath, { force: true }))
- await importPath(filepath, origin)
+ // TODO: fix unanalyzable-dynamic-import to work correctly with jsr.io
+ await import(url.pathToFileURL(scriptPath).toString())
} finally {
- await fs.rm(filepath)
+ rmTemp()
}
}
-export async function importPath(
- filepath: string,
- origin = filepath
-): Promise<void> {
- const contents = await fs.readFile(filepath, 'utf8')
- const { ext, base, dir } = path.parse(filepath)
- const tempFilename = getFilepath(dir, base)
+async function readScript() {
+ const [firstArg] = argv._
+ let script = ''
+ let scriptPath = ''
+ let tempPath = ''
+ let argSlice = 1
+
+ if (argv.eval) {
+ argSlice = 0
+ script = argv.eval
+ tempPath = getFilepath($.cwd, 'zx', argv.ext)
+ } else if (!firstArg || firstArg === '-') {
+ script = await readScriptFromStdin()
+ tempPath = getFilepath($.cwd, 'zx', argv.ext)
+ if (script.length === 0) {
+ printUsage()
+ process.exitCode = 1
+ throw new Error('No script provided')
+ }
+ } else if (/^https?:/.test(firstArg)) {
+ const { name, ext = argv.ext } = path.parse(new URL(firstArg).pathname)
+ script = await readScriptFromHttp(firstArg)
+ tempPath = getFilepath($.cwd, name, ext)
+ } else {
+ script = await fs.readFile(firstArg, 'utf8')
+ scriptPath = firstArg.startsWith('file:')
+ ? url.fileURLToPath(firstArg)
+ : path.resolve(firstArg)
+ }
+ const { ext, base, dir } = path.parse(tempPath || scriptPath)
if (ext === '') {
- return writeAndImport(contents, tempFilename, origin)
+ tempPath = getFilepath(dir, base)
}
if (ext === '.md') {
- return writeAndImport(transformMarkdown(contents), tempFilename, origin)
- }
- if (argv.install) {
- const deps = parseDeps(contents)
- await installDeps(deps, dir, argv.registry)
+ script = transformMarkdown(script)
+ tempPath = getFilepath(dir, base)
}
+ if (argSlice) updateArgv(argv._.slice(argSlice))
+
+ return { script, scriptPath, tempPath }
+}
+
+async function readScriptFromStdin(): Promise<string> {
+ return !process.stdin.isTTY ? stdin() : ''
+}
- injectGlobalRequire(origin)
- // TODO: fix unanalyzable-dynamic-import to work correctly with jsr.io
- await import(url.pathToFileURL(filepath).toString())
+async function readScriptFromHttp(remote: string): Promise<string> {
+ const res = await fetch(remote)
+ if (!res.ok) {
+ console.error(`Error: Can't get ${remote}`)
+ process.exit(1)
+ }
+ return res.text()
}
export function injectGlobalRequire(origin: string) {
test/fixtures/md.http
@@ -0,0 +1,9 @@
+HTTP/1.1 200 OK
+Content-Type: plain/text; charset=UTF-8
+Content-Length: 15
+Server: netcat!
+
+# Title
+```js
+$`echo 'md'`
+```
test/cli.test.js
@@ -191,7 +191,7 @@ describe('cli', () => {
const port = await getPort()
const server = await getServer([resp]).start(port)
const out =
- await $`node build/cli.js --verbose http://127.0.0.1:${port}/echo.mjs`
+ await $`node build/cli.js --verbose http://127.0.0.1:${port}/script.mjs`
assert.match(out.stderr, /test/)
await server.stop()
})
@@ -204,6 +204,16 @@ describe('cli', () => {
await server.stop()
})
+ test('scripts (md) from https', async () => {
+ const resp = await fs.readFile(path.resolve('test/fixtures/md.http'))
+ const port = await getPort()
+ const server = await getServer([resp]).start(port)
+ const out =
+ await $`node build/cli.js --verbose http://127.0.0.1:${port}/script.md`
+ assert.match(out.stderr, /md/)
+ await server.stop()
+ })
+
test('scripts with no extension', async () => {
await $`node build/cli.js test/fixtures/no-extension`
assert.ok(
@@ -237,10 +247,6 @@ describe('cli', () => {
await $`node build/cli.js test/fixtures/markdown.md`
})
- test('markdown scripts are working', async () => {
- await $`node build/cli.js test/fixtures/markdown.md`
- })
-
test('markdown scripts are working for CRLF', async () => {
const p = await $`node build/cli.js test/fixtures/markdown-crlf.md`
assert.ok(p.stdout.includes('Hello, world!'))
test/export.test.js
@@ -75,17 +75,12 @@ describe('cli', () => {
assert.equal(typeof cli.argv.v, 'boolean', 'cli.argv.v')
assert.equal(typeof cli.argv.verbose, 'boolean', 'cli.argv.verbose')
assert.equal(typeof cli.argv.version, 'boolean', 'cli.argv.version')
- assert.equal(typeof cli.importPath, 'function', 'cli.importPath')
assert.equal(typeof cli.injectGlobalRequire, 'function', 'cli.injectGlobalRequire')
assert.equal(typeof cli.isMain, 'function', 'cli.isMain')
assert.equal(typeof cli.main, 'function', 'cli.main')
assert.equal(typeof cli.normalizeExt, 'function', 'cli.normalizeExt')
assert.equal(typeof cli.printUsage, 'function', 'cli.printUsage')
- assert.equal(typeof cli.runScript, 'function', 'cli.runScript')
- assert.equal(typeof cli.scriptFromHttp, 'function', 'cli.scriptFromHttp')
- assert.equal(typeof cli.scriptFromStdin, 'function', 'cli.scriptFromStdin')
assert.equal(typeof cli.transformMarkdown, 'function', 'cli.transformMarkdown')
- assert.equal(typeof cli.writeAndImport, 'function', 'cli.writeAndImport')
})
})