UNPKG

morphir-elm

Version:
151 lines (127 loc) 5.41 kB
#!/usr/bin/env node 'use strict' // NPM imports const path = require('path') const util = require('util') const fs = require('fs') const readdir = util.promisify(fs.readdir) const lstat = util.promisify(fs.lstat) const readFile = util.promisify(fs.readFile) const writeFile = util.promisify(fs.writeFile) const commander = require('commander') const childProc = require('child_process') const fsExtra = require('fs-extra') // Elm imports const worker = require('./Morphir.Elm.DaprCLI').Elm.Morphir.Elm.DaprCLI.init() // Set up Commander const program = new commander.Command() program .name('morphir-dapr ') .description('Generate Dapr Application from Morphir Model') .option('-p, --project-dir <path>', 'Root directory of the project where morphir-dapr.json is located.', '.') .option('-o, --output <path>', 'Target location where the Dapr sources will be sent. Will create it if it does not exist', 'dapr-output') .option('-i, --info', 'Print dapr intermediate output (elm) to STDOUT.') .option('-d, --delete', 'Delete build directory') .parse(process.argv) gen(program.opts().projectDir, program.opts().output, program.opts().debug, program.opts().delete) .then(result => { console.log('Done!') }) .catch((err) => { if (err.code == 'ENOENT') { console.error(`Could not find file at '${err.path}'`) } else { console.error(err) } process.exit(1) }) async function gen(projectDir, output, debug, deleteBuildDir) { const morphirJsonPath = path.join(projectDir, 'morphir-dapr.json') // nosemgrep : path-join-resolve-traversal const morphirJsonContent = await readFile(morphirJsonPath) const morphirJson = JSON.parse(morphirJsonContent.toString()) const sourceFiles = await readElmSources(morphirJson.sourceDirectories) const result = await packageDefAndDaprCodeFromSrc(morphirJson, sourceFiles) if (debug) { console.log(JSON.stringify(result.elmBackendResult)) } const buildDir = 'dapr-stuff' console.log(`Clearing ${buildDir} ...`) fs.rmdirSync(buildDir, { recursive: true }) console.log(`Creating build directory: ${buildDir}`) fs.mkdirSync(buildDir) console.log(`Writing dapr files to ${buildDir} ...`) await writeFile(`${buildDir}/Main.elm`, result.elmBackendResult) console.log(`Copying compilation assets to ${buildDir} ...`) fsExtra.copySync(`${__dirname}/assets/`, buildDir) fsExtra.copySync(`${__dirname}/../src`, buildDir) console.log(`Copying original sources to ${buildDir}`) morphirJson .sourceDirectories .map(async function (dir) { fsExtra.copySync(dir.toString(), buildDir) }) console.log(`Using local elm-platform to perform final compilation`) childProc.execSync(`cd ${buildDir} && elm make Main.elm --output=Main.js`) console.log(`Copying files to output directory...`) // nosemgrep : detect-non-literal-fs-filename if (!fs.existsSync(output)) { fs.mkdirSync(output) // nosemgrep : detect-non-literal-fs-filename } fsExtra.copySync(`${buildDir}/DaprAppShell.js`, `${output}/DaprAppShell.js`) fsExtra.copySync(`${buildDir}/Main.js`, `${output}/Main.js`) fsExtra.copySync(`${buildDir}/package.json`, `${output}/package.json`) if (deleteBuildDir) { fs.rmdirSync(buildDir, { recursive: true }) } return result } async function packageDefAndDaprCodeFromSrc(morphirJson, sourceFiles) { return new Promise((resolve, reject) => { worker.ports.decodeError.subscribe(err => { reject(err) }) worker.ports.packageDefAndDaprCodeFromSrcResult.subscribe(([err, ok]) => { if (err) { reject(err) } else { resolve(ok) } }) worker.ports.packageDefinitionFromSource.send([morphirJson, sourceFiles]) }) } async function readElmSources(dirs) { const readElmSource = async function (filePath) { const content = await readFile(filePath) return { path: filePath, content: content.toString() } } const readDir = async function (currentDir) { const entries = await readdir(currentDir, { withFileTypes: true }) const elmSources = entries .filter(entry => entry.isFile() && entry.name.endsWith('.elm')) // nosemgrep : path-join-resolve-traversal .map(entry => readElmSource(path.join(currentDir, entry.name))) // nosemgrep : path-join-resolve-traversal const subDirSources = entries .filter(entry => entry.isDirectory()) // nosemgrep : path-join-resolve-traversal .map(entry => readDir(path.join(currentDir, entry.name))) // nosemgrep : path-join-resolve-traversal .reduce(async (soFarPromise, nextPromise) => { const soFar = await soFarPromise const next = await nextPromise return soFar.concat(next) }, Promise.resolve([])) return elmSources.concat(await subDirSources) } const sources = await Promise.all( dirs.map(async (dir) => Promise.all( await readDir(dir) ) ) ) return sources.flat() }