UNPKG

@bytecodealliance/jco

Version:

JavaScript tooling for working with WebAssembly Components

152 lines (143 loc) 5.02 kB
import { resolve, basename, extname } from "node:path"; import { writeFile } from "node:fs/promises"; import { readFile, isWindows, styleText } from "../common.js"; import { $init, tools } from "../../obj/wasm-tools.js"; const { print: printFn, parse: parseFn, componentWit: componentWitFn, componentNew: componentNewFn, componentEmbed: componentEmbedFn, metadataAdd: metadataAddFn, metadataShow: metadataShowFn, } = tools; export async function parse(file, opts) { await $init; const source = (await readFile(file)).toString(); const output = parseFn(source); await writeFile(opts.output, output); } export async function print(file, opts) { await $init; const source = await readFile(file); const output = printFn(source); if (opts.output) { await writeFile(opts.output, output); } else { console.log(output); } } export async function componentWit(file, opts) { await $init; const source = await readFile(file); const output = componentWitFn(source, opts.document); if (opts.output) { await writeFile(opts.output, output); } else { console.log(output); } } export async function componentNew(file, opts) { await $init; const source = file ? await readFile(file) : null; let adapters = []; if (opts.wasiReactor && opts.wasiCommand) { throw new Error("Must select one of --wasi-command or --wasi-reactor"); } if (opts.wasiReactor) { adapters = [ [ "wasi_snapshot_preview1", (await readFile(new URL("../../lib/wasi_snapshot_preview1.reactor.wasm", import.meta.url))).buffer, ], ]; } else if (opts.wasiCommand) { adapters = [ [ "wasi_snapshot_preview1", (await readFile(new URL("../../lib/wasi_snapshot_preview1.command.wasm", import.meta.url))).buffer, ], ]; } if (opts.adapt) { adapters = adapters.concat( await Promise.all( opts.adapt.map(async (adapt) => { let adapter; if (adapt.includes("=")) { adapter = adapt.split("="); } else { adapter = [basename(adapt).slice(0, -extname(adapt).length), adapt]; } adapter[1] = await readFile(adapter[1]); return adapter; }), ), ); } const output = componentNewFn(source, adapters); await writeFile(opts.output, output); } export async function componentEmbed(file, opts) { await $init; if (opts.metadata) { opts.metadata = opts.metadata.map((meta) => { const [field, data = ""] = meta.split("="); const [name, version = ""] = data.split("@"); return [field, [[name, version]]]; }); } const source = file ? await readFile(file) : null; opts.binary = source; opts.witPath = (isWindows ? "//?/" : "") + resolve(opts.wit); const output = componentEmbedFn(opts); await writeFile(opts.output, output); } export async function metadataAdd(file, opts) { await $init; const metadata = opts.metadata.map((meta) => { const [field, data = ""] = meta.split("="); const [name, version = ""] = data.split("@"); return [field, [[name, version]]]; }); const source = await readFile(file); const output = metadataAddFn(source, metadata); await writeFile(opts.output, output); } export async function metadataShow(file, opts) { await $init; const source = await readFile(file); let output = "", stack = [1]; const meta = metadataShowFn(source); if (opts.json) { console.log(JSON.stringify(meta, null, 2)); } else { for (const { name, metaType, producers } of meta) { output += " ".repeat(stack.length - 1); const indent = " ".repeat(stack.length); if (metaType.tag === "component") { output += `${styleText("bold", `[component${name ? " " + name : ""}]`)}\n`; if (metaType.val > 0) { stack.push(metaType.val); } } else { output += `${styleText("bold", `[module${name ? " " + name : ""}]`)}\n`; } if (producers.length === 0) { output += `${indent}(no metadata)\n`; } for (const [field, items] of producers) { for (const [name, version] of items) { output += `${indent}${(field + ":").padEnd(13, " ")} ${name}${version ? `${styleText("cyan", version)}` : ""}\n`; } } output += "\n"; if (stack[stack.length - 1] === 0) { stack.pop(); } stack[stack.length - 1]--; } process.stdout.write(output); } }