UNPKG

@bytecodealliance/jco

Version:

JavaScript tooling for working with WebAssembly Components

169 lines (160 loc) 5.43 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); } }