UNPKG

@oada/cli

Version:

CLI OADA client

196 lines 5.86 kB
import { createReadStream, createWriteStream } from 'node:fs'; import { extname, isAbsolute, join } from 'node:path'; import { URL } from 'node:url'; import { pipeline } from 'node:stream/promises'; import { Minimatch } from 'minimatch'; import { highlight } from 'cli-highlight'; import { parse } from 'concatjson'; import { request } from 'gaxios'; import { stringify } from 'ndjson'; import { oadaify } from '@oada/oadaify'; import 'ts-node/register/transpile-only'; function inputType(inString, { domain, domains }) { if (inString === '-') { return 3; } if (isAbsolute(inString)) { return 1; } try { const { protocol, host } = new URL(inString); if (protocol === 'file:') { return 0; } if ([domain, ...Object.keys(domains)].includes(host)) { return 1; } return 2; } catch { return 0; } } async function outputType(outString, { tty }) { if (outString === '-') { if (tty) { return 5; } return 4; } try { const { protocol } = new URL(outString); return protocol === 'file:' ? 0 : 2; } catch { return 0; } } export const importable = ['.ts', '.js']; export async function loadFile(inString) { const path = join(process.cwd(), inString); const { default: data } = (await import(path)); return data; } function inputChain(conn, inString, config) { switch (inputType(inString, config)) { case 3: { return [process.stdin, parse()]; } case 0: { const extension = extname(inString); if (importable.includes(extension)) { return [ async function* () { yield loadFile(inString); }, ]; } return [createReadStream(inString), parse()]; } case 1: { return [ async function* () { const paths = expandPath(conn, inString); for await (const path of paths) { const { data } = await conn.get({ path }); yield data; } }, ]; } case 2: { return [ async function* () { const { data } = await request({ responseType: 'json', url: inString, }); yield data; }, ]; } default: { throw new Error(`Unsupported input type: ${inString}`); } } } export async function* expandPath(conn, path) { let parts; let origin; try { let pathname; ({ pathname, origin } = new URL(path)); parts = pathname.split('/'); } catch { parts = path.split('/'); origin = ''; } const trailing = path.endsWith('/'); yield* expand('/', { conn, parts, trailing, origin }); } async function* expand(r, { conn, parts, trailing, origin, }) { const p = Array.from(parts); let root = r; let expanded = false; for (const part of parts) { p.shift(); const mm = new Minimatch(part); if (mm.set.length <= 1 && mm.set[0]?.length <= 1 && ['string', 'undefined'].includes(typeof mm.set[0]?.[0])) { root = join(root, part); continue; } try { const { data: children } = await conn.get({ path: join('/', root) }); if (!children || typeof children !== 'object') { throw new TypeError('No children'); } if (Buffer.isBuffer(children)) { throw new TypeError('Cannot traverse non-JSON'); } for (const child in oadaify(children)) { if (mm.match(child)) { yield* expand(join(root, child), { conn, parts: p, trailing, origin, }); expanded = true; } } } catch { } } if (!expanded) { yield origin + join('/', root + (trailing ? '/' : '')); } } export async function input(conn, paths, config, handler) { for (const path of Array.isArray(paths) ? paths : [paths]) { const [source, ...chain] = inputChain(conn, path, config); await pipeline(source, ...chain, handler); } } async function outputChain(outString, config) { switch (await outputType(outString, config)) { case 5: { return [ async function* (source) { for await (const data of source) { yield highlight(`${JSON.stringify(data, undefined, 2)}\n`, { language: 'json', }); } }, process.stdout, ]; } case 4: { return [stringify(), process.stdout]; } case 0: { return [stringify(), createWriteStream(outString)]; } case 2: { return [ async function* (source) { for await (const data of source) { yield request({ url: outString, data }); } }, ]; } default: { throw new Error(`Unsupported output type: ${outString}`); } } } export async function output(file, handler, config) { const chain = await outputChain(file, config); return pipeline(handler, ...chain); } //# sourceMappingURL=io.js.map