diff --git a/cli/morphir-elm-gen.js b/cli/morphir-elm-gen.js index 45433c374..2e6ae49be 100644 --- a/cli/morphir-elm-gen.js +++ b/cli/morphir-elm-gen.js @@ -5,6 +5,7 @@ const path = require('path') const commander = require('commander') const cli = require('./cli') +const execa = require('execa') //logging require('log-timestamp') @@ -25,12 +26,32 @@ program .option('-ls, --include ', 'Limit what will be included.', '') .parse(process.argv) -cli.gen(program.opts().input, path.resolve(program.opts().output), program.opts()) - .then(() => { - console.log("Done.") - }) - .catch((err) => { - console.error(err) - process.exit(1) - }) +const options = program.opts(); +const backendTarget = options.target; +const showDeprecationMessage = (cmd, opts) => { + console.warn(`This Command is Deprecated. Switching to morphir ${cmd}-gen`); + console.info(`Running => morphir ${cmd}-gen ${opts}`); +} + +switch (backendTarget) { + case "TypeScript": + const copyDeps = (options.copyDeps) ? "--copy-deps" : ""; + const cmdOptions = `--input=${program.opts().input} --output=${program.opts().output} ${copyDeps}` + showDeprecationMessage("typescript", cmdOptions) + execa(`morphir typescript-gen ${cmdOptions}`).stdout.pipe(process.stdout) + break; + + default: + cli.gen(program.opts().input, path.resolve(program.opts().output), program.opts()) + .then(() => { + console.log("Done.") + }) + .catch((err) => { + console.error(err) + process.exit(1) + }) + break; +} + + diff --git a/cli2/cli.ts b/cli2/cli.ts index e711097a2..8a3840307 100644 --- a/cli2/cli.ts +++ b/cli2/cli.ts @@ -546,4 +546,5 @@ export = { copyRedistributables, testCoverage, worker, + copyRecursiveSync }; diff --git a/cli2/morphir-typescript-gen.ts b/cli2/morphir-typescript-gen.ts new file mode 100644 index 000000000..323b7d63d --- /dev/null +++ b/cli2/morphir-typescript-gen.ts @@ -0,0 +1,154 @@ +#!/usr/bin/env node + +//NPM imports +import * as fs from "fs"; +import path from 'path'; +import { Command } from 'commander' +import cli = require('./cli') +import * as util from 'util' +import prettier from "prettier" + +const fsExists = util.promisify(fs.exists); +const fsWriteFile = util.promisify(fs.writeFile); +const fsMakeDir = util.promisify(fs.mkdir); +const fsReadFile = util.promisify(fs.readFile); +const worker = require("./../Morphir.Elm.CLI").Elm.Morphir.Elm.CLI.init(); + +require('log-timestamp') + +const program = new Command() +program + .name('morphir typescript-gen') + .description('Generate typescript code from Morphir IR') + .option('-i, --input ', 'Source location where the Morphir IR will be loaded from.', 'morphir-ir.json') + .option('-o, --output ', 'Target location where the generated code will be saved.', './dist') + .option('-c, --copy-deps', 'Copy the dependencies used by the generated code to the output path.', false) + .parse(process.argv) + +interface CommandOptions { + input: string, + output: string, + copyDeps: boolean +} + +const mapCommandOptions = (programOpts: any) => { + return { + target: "TypeScript", + input: programOpts.input, + output: programOpts.output, + copyDeps: programOpts.copyDeps, + } as CommandOptions +} + +const generate = async ( + options: CommandOptions, + ir: string, + testSuite: Array +): Promise => { + + return new Promise((resolve, reject) => { + worker.ports.jsonDecodeError.subscribe((err: any) => { + reject(err); + }); + worker.ports.generateResult.subscribe(([err, ok]: any) => { + if (err) { + reject(err); + } else { + resolve(ok); + } + }); + + worker.ports.generate.send([options, ir, testSuite]); + }); +}; + + + +const gen = async ( + input: string, + outputPath: string, + options: CommandOptions +) => { + + await fsMakeDir(outputPath, {recursive: true}); + + const morphirIrJson: Buffer = await fsReadFile(path.resolve(input)); + + let morphirTestsJSONContent: Array = []; + + try { + const bufferContent = await fsReadFile(path.resolve('./morphir-tests.json')) + morphirTestsJSONContent = JSON.parse(bufferContent.toString()) + } catch (_) { + console.log("could not read morphir-tests.json, defaulting to an empty test!") + } + + const generatedFiles: string[] = await generate( + options, + JSON.parse(morphirIrJson.toString()), + morphirTestsJSONContent + ) + + const writePromises = generatedFiles.map( + async ([[dirPath, fileName], content]: any) => { + const fileDir: string = dirPath.reduce( + (accum: string, next: string) => path.join(accum, next), + outputPath + ) + + await fsMakeDir(fileDir, { recursive: true }) + + const filePath: string = path.join(fileDir, fileName) + const incomingContent = prettier.format(content, { parser: "typescript" }) + + if(await fsExists(filePath)) { + const existingContent: Buffer = await fsReadFile(filePath) + if (existingContent.toString() == incomingContent) { + //console.log(`No Changes Detected - ${filePath}`); + } + else { + console.log(`UPDATE - ${filePath}`) + } + } + else { + console.log(`INSERT - ${filePath}`); + } + + await fsWriteFile(filePath, incomingContent) + } + ); + + const filesToDelete = await cli.findFilesToDelete(outputPath, generatedFiles); + + const deletePromises = filesToDelete.map(async (fileToDelete: string) => { + console.log(`DELETE - ${fileToDelete}`); + return fs.unlinkSync(fileToDelete); + }); + + if (options.copyDeps) { + const copyFiles = (src: string, dest: string) => { + const sourceDirectory: string = path.join( + path.dirname(__dirname), + "..", + "redistributable", + src + ); + cli.copyRecursiveSync(sourceDirectory, outputPath); + }; + + copyFiles("TypeScript/", outputPath) + } + + return Promise.all(writePromises.concat(deletePromises)); +}; + + + +gen(program.opts().input, path.resolve(program.opts().output), mapCommandOptions(program.opts())) + .then(() => { + console.log("Done") + }) + .catch((err) => { + console.log(err) + process.exit(1) + }) diff --git a/cli2/morphir.ts b/cli2/morphir.ts index 6bd421a01..6d20539e4 100644 --- a/cli2/morphir.ts +++ b/cli2/morphir.ts @@ -11,11 +11,13 @@ const program = new Command() program .version(packageJson.version, '-v, --version') .command('make', 'Translate Elm sources to Morphir IR') - .command('scala-gen','Generate scala code from Morphir IR') .command('json-schema-gen', 'Generate Json Schema from the Morphir IR') .command('stats', 'Collect morphir features used in a model into a document') - .command('dockerize', 'Creates a docker image of a Morphir IR and Morphir Develop') + .command('dockerize', 'Creates a docker file of a Morphir IR and Morphir Develop') .command('test-coverage', 'Generates report on number of branches in a Morphir value and TestCases covered') .command('generate-test-data', 'Creates a docker image of a Morphir IR and Morphir Develop') .command('init', 'Launches an interactive session to initialize a new morphir project.') + // transpile commands + .command('scala-gen','Generate scala code from Morphir IR') + .command('typescript-gen','Generate typescript code from Morphir IR') .parse(process.argv) \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 2b7dbb180..1756db95e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -156,7 +156,7 @@ function morphirElmMakeJsonSchema(projectDir, outputPath, options = {}) { } function morphirElmGen(inputPath, outputDir, target) { - args = ['./cli/morphir-elm.js', 'gen', '-i', inputPath, '-o', outputDir, '-t', target] + args = ['./cli/morphir-elm.js', 'gen', '-i', inputPath, '-o', outputDir, '-t', target, '-c'] console.log("Running: " + args.join(' ')); return execa('node', args, { stdio }) } @@ -356,19 +356,25 @@ testIntegration = series( testIntegrationClean, testIntegrationMake, testCreateCSV, - parallel( - testIntegrationMorphirTest, - //testIntegrationSpark, - series( - testIntegrationGenScala, - testIntegrationBuildScala, - ), - series( - testIntegrationGenTypeScript, - testIntegrationTestTypeScript, - ), - ),testIntegrationDockerize, - testIntegrationJsonSchemaGen + testIntegrationMorphirTest, + testIntegrationGenScala, + testIntegrationBuildScala, + testIntegrationGenTypeScript, + testIntegrationTestTypeScript, + // parallel( + // testIntegrationMorphirTest, + // //testIntegrationSpark, + // series( + // testIntegrationGenScala, + // testIntegrationBuildScala, + // ), + // series( + // testIntegrationGenTypeScript, + // testIntegrationTestTypeScript, + // ), + // ), + testIntegrationDockerize, + testIntegrationJsonSchemaGen )