@oada/cli
Version:
CLI OADA client
196 lines • 5.86 kB
JavaScript
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