UNPKG

@taqueria/plugin-archetype

Version:

A taqueria plugin for compiling Archetype smart contracts

98 lines (85 loc) 3.24 kB
import { execCmd, getContracts, getDockerImage, ProxyTaskArgs, RequestArgs, sendAsyncErr, sendAsyncRes, sendErr, sendJsonRes, } from '@taqueria/node-sdk'; import { basename, extname, join } from 'path'; import { match } from 'ts-pattern'; // Should point to the latest stable version, so it needs to be updated as part of our release process. const ARCHETYPE_DEFAULT_IMAGE = 'completium/archetype:1.5.2'; const ARCHETYPE_IMAGE_ENV_VAR = 'TAQ_ARCHETYPE_IMAGE'; export const getArchetypeDockerImage = (): string => getDockerImage(ARCHETYPE_DEFAULT_IMAGE, ARCHETYPE_IMAGE_ENV_VAR); interface Opts extends ProxyTaskArgs.t { sourceFile?: string; } const getInputFilename = (opts: Opts) => (sourceFile: string) => { const inputFile = basename(sourceFile, extname(sourceFile)); return join(opts.config.contractsDir ?? 'contracts', `${inputFile}.arl`); }; const getContractArtifactFilename = (opts: Opts) => (sourceFile: string) => { const outFile = basename(sourceFile, extname(sourceFile)); return join(opts.config.artifactsDir ?? 'contracts', `${outFile}.tz`); }; const getDecompileCommand = (opts: Opts) => (sourceFile: string) => { const { projectDir } = opts; const inputFile = getInputFilename(opts)(sourceFile); const baseCommand = `DOCKER_DEFAULT_PLATFORM=linux/amd64 docker run --rm -v \"${projectDir}\":/project -u $(id -u):$(id -g) -w /project ${getArchetypeDockerImage()} -d ${inputFile}`; const outFile = `-o ${getContractArtifactFilename(opts)(sourceFile)}`; const cmd = `${baseCommand} ${outFile}`; return cmd; }; const decompileContract = (opts: Opts) => (sourceFile: string): Promise<{ contract: string; artifact: string }> => // const sourceAbspath = join(opts.contractsDir, sourceFile) execCmd(getDecompileCommand(opts)(sourceFile)) .then(({ stderr }) => { // How should we output warnings? if (stderr.length > 0) sendErr(stderr); return { contract: sourceFile, artifact: getContractArtifactFilename(opts)(sourceFile), }; }) .catch(err => { sendErr(' '); sendErr(err.message.split('\n').slice(1).join('\n')); return Promise.resolve({ contract: sourceFile, artifact: 'Not decompiled', }); }); const decompileAll = (opts: Opts): Promise<{ contract: string; artifact: string }[]> => { const contracts = getContracts(/\.arl$/, opts.config); return Promise.all(contracts) .then(entries => entries.map(decompileContract(opts))) .then(processes => processes.length > 0 ? processes : [{ contract: 'None found', artifact: 'N/A' }] ) .then(promises => Promise.all(promises)); }; const decompile = (parsedArgs: RequestArgs.t) => { const unsafeOpts = parsedArgs as unknown as Opts; return match(unsafeOpts) .when(unsafeOpts => unsafeOpts.task === 'get-image', () => sendAsyncRes(getArchetypeDockerImage())) .otherwise(() => { const p = unsafeOpts.sourceFile ? decompileContract(unsafeOpts)(unsafeOpts.sourceFile) .then(result => [result]) : decompileAll(unsafeOpts) .then(results => { if (results.length === 0) sendErr('No contracts found to decompile.'); return results; }); return p .then(sendJsonRes) .catch(err => sendAsyncErr(err, false)); }); }; export default decompile;