@eeue56/derw
Advanced tools
Comparing version 0.0.3-4 to 0.0.3-5
#!/usr/bin/env ts-node | ||
export declare function main(): Promise<void>; | ||
export declare function main(): Promise<number>; |
355
build/cli.js
#!/usr/bin/env ts-node | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.main = void 0; | ||
const bach_1 = require("@eeue56/bach/build/bach"); | ||
const baner_1 = require("@eeue56/baner"); | ||
const result_1 = require("@eeue56/ts-core/build/main/lib/result"); | ||
const child_process_1 = require("child_process"); | ||
const fs_1 = require("fs"); | ||
const promises_1 = require("fs/promises"); | ||
const path_1 = __importDefault(require("path")); | ||
const util = __importStar(require("util")); | ||
const compile_1 = require("./compile"); | ||
const generator_1 = require("./generator"); | ||
const package_1 = require("./package"); | ||
const derwParser = __importStar(require("./parser")); | ||
async function ensureDirectoryExists(directory) { | ||
try { | ||
const lstat = await fs_1.promises.lstat(directory); | ||
if (!lstat.isDirectory()) { | ||
await fs_1.promises.mkdir(directory, { recursive: true }); | ||
} | ||
} | ||
catch (error) { | ||
await fs_1.promises.mkdir(directory, { recursive: true }); | ||
} | ||
} | ||
function filterBodyForName(module, name) { | ||
const blocks = []; | ||
for (var element of module.body) { | ||
switch (element.kind) { | ||
case "Function": | ||
case "Const": { | ||
if (element.name === name) { | ||
blocks.push(element); | ||
} | ||
break; | ||
} | ||
case "Import": { | ||
for (var module_ of element.modules) { | ||
if (module_.name === name) { | ||
blocks.push(element); | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
case "UnionType": | ||
case "TypeAlias": { | ||
if (element.type.name === name) { | ||
blocks.push(element); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
return blocks; | ||
} | ||
function getImports(module) { | ||
return module.body.filter((block) => block.kind === "Import"); | ||
} | ||
async function fileExists(name) { | ||
try { | ||
await fs_1.promises.access(name); | ||
} | ||
catch (e) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function runFile(target, fullName) { | ||
let child; | ||
switch (target) { | ||
case "js": { | ||
child = child_process_1.spawnSync(`npx`, [`node`, `${fullName}`], { | ||
stdio: "inherit", | ||
encoding: "utf-8", | ||
}); | ||
break; | ||
} | ||
case "ts": { | ||
child = child_process_1.spawnSync(`npx`, [`ts-node`, `${fullName}`], { | ||
stdio: "inherit", | ||
encoding: "utf-8", | ||
}); | ||
break; | ||
} | ||
} | ||
} | ||
const compile_1 = require("./cli/compile"); | ||
const init_1 = require("./cli/init"); | ||
const install_1 = require("./cli/install"); | ||
const testing_1 = require("./cli/testing"); | ||
const utils_1 = require("./cli/utils"); | ||
function parseCliCommand() { | ||
@@ -123,2 +22,4 @@ if (typeof process.argv[2] === "undefined") { | ||
return result_1.Ok("test"); | ||
case "install": | ||
return result_1.Ok("install"); | ||
default: { | ||
@@ -129,194 +30,2 @@ return result_1.Err(`Unknown command \`${process.argv[2]}\``); | ||
} | ||
const compileParser = baner_1.parser([ | ||
baner_1.longFlag("files", "File names to be compiled", baner_1.variableList(baner_1.string())), | ||
baner_1.longFlag("target", "Target TS, JS or Derw output", baner_1.oneOf(["ts", "js", "derw", "elm"])), | ||
baner_1.longFlag("output", "Output directory name", baner_1.string()), | ||
baner_1.longFlag("verify", "Run typescript compiler on generated files to ensure valid output", baner_1.empty()), | ||
baner_1.longFlag("debug", "Show a parsed object tree", baner_1.empty()), | ||
baner_1.longFlag("only", "Only show a particular object", baner_1.string()), | ||
baner_1.longFlag("run", "Should be run via ts-node/node", baner_1.empty()), | ||
baner_1.longFlag("format", "Format the files given in-place", baner_1.empty()), | ||
baner_1.longFlag("quiet", "Keep it short and sweet", baner_1.empty()), | ||
baner_1.bothFlag("h", "help", "This help text", baner_1.empty()), | ||
]); | ||
function showHelp() { | ||
console.log("Let's write some Derw code"); | ||
console.log("To get started:"); | ||
console.log("Initialize the current directory via `init`"); | ||
console.log("Or provide entry files via `--files`"); | ||
console.log("Or run me without args inside a package directory"); | ||
console.log(baner_1.help(compileParser)); | ||
} | ||
async function getDerwFiles() { | ||
return await (await promises_1.readdir("./src")) | ||
.map((file) => path_1.default.join("src", file)) | ||
.filter((file) => file.endsWith("derw")); | ||
} | ||
async function compileFiles(program, isInPackageDirectory) { | ||
const debugMode = program.flags["debug"].isPresent; | ||
const files = isInPackageDirectory | ||
? await getDerwFiles() | ||
: program.flags.files.arguments.value; | ||
const isFormat = program.flags.format.isPresent; | ||
const outputDir = program.flags.output.isPresent | ||
? program.flags.output.arguments.value | ||
: "./"; | ||
const isStdout = outputDir === "/dev/stdout"; | ||
if (!isStdout) { | ||
await ensureDirectoryExists(outputDir); | ||
} | ||
const target = isFormat | ||
? "derw" | ||
: program.flags.target.isPresent | ||
? program.flags.target.arguments.value | ||
: "ts"; | ||
const shouldRun = program.flags.run.isPresent; | ||
const isQuiet = program.flags.quiet.isPresent; | ||
if (!isQuiet) { | ||
if (isInPackageDirectory) { | ||
console.log("Compiling package..."); | ||
} | ||
console.log(`Generating ${files.length} files...`); | ||
} | ||
const processedFiles = []; | ||
await Promise.all(files.map(async function compile(fileName) { | ||
if (processedFiles.indexOf(fileName) > -1) { | ||
return; | ||
} | ||
processedFiles.push(fileName); | ||
const dotParts = fileName.split("."); | ||
const extension = dotParts[dotParts.length - 1]; | ||
if (extension !== "derw") { | ||
console.log("Warning: Derw files should be called .derw"); | ||
console.log(`Try renaming ${fileName} to ${dotParts | ||
.slice(0, -1) | ||
.join(".")}.derw`); | ||
} | ||
const derwContents = (await fs_1.promises.readFile(fileName)).toString(); | ||
const isMain = files.indexOf(fileName) > -1; | ||
const parsed = derwParser.parse(derwContents, isMain ? "Main" : fileName); | ||
if (parsed.errors.length > 0) { | ||
console.log(`Failed to parse ${fileName} due to:`); | ||
console.log(parsed.errors.join("\n")); | ||
return; | ||
} | ||
const dir = path_1.default.dirname(fileName); | ||
const imports = []; | ||
getImports(parsed).forEach((import_) => { | ||
import_ = import_; | ||
import_.modules.forEach((module) => { | ||
if (module.namespace === "Global") | ||
return; | ||
const moduleName = module.name.slice(1, -1); | ||
imports.push(path_1.default.normalize(path_1.default.join(dir, moduleName))); | ||
}); | ||
}); | ||
for (const import_ of imports) { | ||
const fileWithDerwExtension = import_ + `.derw`; | ||
const isDerw = await fileExists(fileWithDerwExtension); | ||
if (isDerw) { | ||
await compile(fileWithDerwExtension); | ||
continue; | ||
} | ||
// check if ts/js versions of the file exist | ||
const fileWithTsExtension = import_ + `.ts`; | ||
const fileWithJsExtension = import_ + `.js`; | ||
let doesFileExist = false; | ||
if (await fileExists(fileWithTsExtension)) { | ||
doesFileExist = true; | ||
} | ||
else if (await fileExists(fileWithJsExtension)) { | ||
doesFileExist = true; | ||
} | ||
if (!doesFileExist) { | ||
console.log(`Warning! Failed to find \`${import_}\` as either derw, ts or js`); | ||
} | ||
} | ||
if (debugMode) { | ||
if (program.flags["only"].isPresent) { | ||
if (program.flags["only"].arguments.kind === "err") { | ||
console.log(program.flags.only.arguments.error); | ||
} | ||
else { | ||
const name = program.flags["only"].arguments.value; | ||
const blocks = filterBodyForName(parsed, name); | ||
console.log(`Filtering for ${name}...`); | ||
console.log(util.inspect(blocks, true, null, true)); | ||
} | ||
return; | ||
} | ||
console.log(util.inspect(parsed, true, null, true)); | ||
return; | ||
} | ||
const generated = generator_1.generate(target, parsed); | ||
if (program.flags.verify.isPresent && target === "ts") { | ||
const output = compile_1.compileTypescript(generated); | ||
if (output.kind === "err") { | ||
console.log(`Failed to compile ${fileName} due to`, output.error.map((e) => e.messageText).join("\n")); | ||
} | ||
else { | ||
console.log(`Successfully compiled ${fileName}`); | ||
} | ||
} | ||
if (isStdout) { | ||
console.log(generated); | ||
return; | ||
} | ||
if (fileName.indexOf("/") > -1) { | ||
const dirName = fileName.split("/").slice(0, -1).join("/"); | ||
await ensureDirectoryExists(path_1.default.join(outputDir, dirName)); | ||
} | ||
const outputName = dotParts.slice(0, -1).join(".") + "." + target; | ||
const fullName = path_1.default.join(outputDir, outputName); | ||
await promises_1.writeFile(fullName, generated); | ||
if (shouldRun) { | ||
runFile(target, fullName); | ||
} | ||
})); | ||
if (!isQuiet) { | ||
console.log("Processed:", processedFiles); | ||
} | ||
} | ||
async function copyTSconfig() { | ||
const tsconfig = { | ||
compilerOptions: { | ||
target: "es2017", | ||
module: "commonjs", | ||
declaration: true, | ||
outDir: "./build/", | ||
rootDirs: ["src"], | ||
strict: true, | ||
moduleResolution: "node", | ||
types: ["node"], | ||
esModuleInterop: true, | ||
skipLibCheck: true, | ||
forceConsistentCasingInFileNames: true, | ||
}, | ||
include: ["src/**/*"], | ||
exclude: ["node_modules/**"], | ||
}; | ||
if (await fileExists("tsconfig.json")) { | ||
console.log("Already got a tsconfig!"); | ||
return -1; | ||
} | ||
await promises_1.writeFile("tsconfig.json", JSON.stringify(tsconfig, null, 4)); | ||
} | ||
async function init() { | ||
const packageName = path_1.default.basename(process.cwd()); | ||
const package_ = package_1.Package(packageName, [], []); | ||
if (await fileExists("derw-package.json")) { | ||
console.log("Package already initialized!"); | ||
return -1; | ||
} | ||
await promises_1.writeFile("derw-package.json", package_1.exportPackage(package_)); | ||
await copyTSconfig(); | ||
await ensureDirectoryExists("src"); | ||
} | ||
async function runTests(isInPackageDirectory) { | ||
if (!isInPackageDirectory) { | ||
console.log("Must run tests from the root of a package directory."); | ||
process.exit(1); | ||
} | ||
await bach_1.runner(); | ||
} | ||
function showCommandHelp() { | ||
@@ -333,46 +42,22 @@ console.log("To get started:"); | ||
showCommandHelp(); | ||
return; | ||
process.exit(1); | ||
} | ||
const isInPackageDirectory = await utils_1.fileExists("derw-package.json"); | ||
switch (command.value) { | ||
case "compile": { | ||
const program = baner_1.parse(compileParser, process.argv); | ||
if (program.flags["h/help"].isPresent) { | ||
showHelp(); | ||
return; | ||
} | ||
const errors = baner_1.allErrors(program); | ||
if (errors.length > 0) { | ||
console.log("Errors:"); | ||
console.log(errors.join("\n")); | ||
process.exit(1); | ||
} | ||
const isInPackageDirectory = await fileExists("derw-package.json"); | ||
if (!program.flags.files.isPresent && !isInPackageDirectory) { | ||
console.log("You must provide at least one file via --files"); | ||
console.log("Or be in a directory wit derw-package.json."); | ||
process.exit(1); | ||
} | ||
await compileFiles(program, isInPackageDirectory); | ||
return; | ||
await compile_1.compileFiles(isInPackageDirectory); | ||
return 0; | ||
} | ||
case "init": { | ||
await init(); | ||
console.log("Project initialized!"); | ||
console.log("Put your files in `src`"); | ||
console.log("Compile your project via `derw compile`"); | ||
console.log("Run tests via `derw test`"); | ||
return; | ||
await init_1.init(isInPackageDirectory); | ||
return 0; | ||
} | ||
case "install": { | ||
await install_1.install(isInPackageDirectory); | ||
return 0; | ||
} | ||
case "test": { | ||
const program = baner_1.parse(compileParser, process.argv); | ||
const errors = baner_1.allErrors(program); | ||
if (errors.length > 0) { | ||
console.log("Errors:"); | ||
console.log(errors.join("\n")); | ||
process.exit(1); | ||
} | ||
const isInPackageDirectory = await fileExists("derw-package.json"); | ||
await compileFiles(program, isInPackageDirectory); | ||
await runTests(isInPackageDirectory); | ||
return; | ||
await compile_1.compileFiles(isInPackageDirectory); | ||
await testing_1.runTests(isInPackageDirectory); | ||
return 0; | ||
} | ||
@@ -379,0 +64,0 @@ } |
@@ -21,3 +21,4 @@ import { Result } from "@eeue56/ts-core/build/main/lib/result"; | ||
export declare function Package(name: string, exposing: PackageModule[], dependencies: Dependency[]): Package; | ||
export declare function addDependency(dependency: Dependency, package_: Package): Package; | ||
export declare function exportPackage(package_: Package): string; | ||
export declare function decodePackage(potentialPackage: any): Result<string, Package>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.decodePackage = exports.exportPackage = exports.Package = exports.dependenciesFromRecord = exports.Dependency = exports.PackageModule = void 0; | ||
exports.decodePackage = exports.exportPackage = exports.addDependency = exports.Package = exports.dependenciesFromRecord = exports.Dependency = exports.PackageModule = void 0; | ||
const adeilad_1 = require("@eeue56/adeilad"); | ||
@@ -42,6 +42,17 @@ function PackageModule(name) { | ||
], Package); | ||
function addDependency(dependency, package_) { | ||
for (const dep of package_.dependencies) { | ||
if (dep.name === dependency.name) { | ||
dep.version = dependency.version; | ||
return package_; | ||
} | ||
} | ||
package_.dependencies.push(dependency); | ||
return package_; | ||
} | ||
exports.addDependency = addDependency; | ||
function exportPackage(package_) { | ||
const dependencies = {}; | ||
for (const dependency of package_.dependencies) { | ||
dependencies[dependency.name] = dependencies.version; | ||
dependencies[dependency.name] = dependency.version; | ||
} | ||
@@ -48,0 +59,0 @@ return JSON.stringify({ |
{ | ||
"name": "@eeue56/derw", | ||
"version": "0.0.3-4", | ||
"version": "0.0.3-5", | ||
"description": "An Elm-inspired language that transpiles to TypeScript", | ||
@@ -36,4 +36,4 @@ "main": "index.js", | ||
"dependencies": { | ||
"@eeue56/adeilad": "^0.0.1", | ||
"@eeue56/bach": "^0.0.10", | ||
"@eeue56/adeilad": "^0.0.1", | ||
"@eeue56/baner": "^0.0.2", | ||
@@ -40,0 +40,0 @@ "@eeue56/ts-core": "^1.1.0", |
424
src/cli.ts
#!/usr/bin/env ts-node | ||
import { runner } from "@eeue56/bach/build/bach"; | ||
import { | ||
allErrors, | ||
bothFlag, | ||
empty, | ||
help, | ||
longFlag, | ||
oneOf, | ||
parse, | ||
parser, | ||
Program, | ||
string, | ||
variableList, | ||
} from "@eeue56/baner"; | ||
import { Err, Ok, Result } from "@eeue56/ts-core/build/main/lib/result"; | ||
import { spawnSync } from "child_process"; | ||
import { promises } from "fs"; | ||
import { readdir, writeFile } from "fs/promises"; | ||
import path from "path"; | ||
import * as util from "util"; | ||
import { compileTypescript } from "./compile"; | ||
import { generate, Target } from "./generator"; | ||
import { exportPackage, Package } from "./package"; | ||
import * as derwParser from "./parser"; | ||
import { Block, Import, Module } from "./types"; | ||
import { compileFiles } from "./cli/compile"; | ||
import { init } from "./cli/init"; | ||
import { install } from "./cli/install"; | ||
import { runTests } from "./cli/testing"; | ||
import { fileExists } from "./cli/utils"; | ||
async function ensureDirectoryExists(directory: string): Promise<void> { | ||
try { | ||
const lstat = await promises.lstat(directory); | ||
if (!lstat.isDirectory()) { | ||
await promises.mkdir(directory, { recursive: true }); | ||
} | ||
} catch (error) { | ||
await promises.mkdir(directory, { recursive: true }); | ||
} | ||
} | ||
type CliCommand = "init" | "compile" | "test" | "install"; | ||
function filterBodyForName(module: Module, name: string): Block[] { | ||
const blocks = [ ]; | ||
for (var element of module.body) { | ||
switch (element.kind) { | ||
case "Function": | ||
case "Const": { | ||
if (element.name === name) { | ||
blocks.push(element); | ||
} | ||
break; | ||
} | ||
case "Import": { | ||
for (var module_ of element.modules) { | ||
if (module_.name === name) { | ||
blocks.push(element); | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
case "UnionType": | ||
case "TypeAlias": { | ||
if (element.type.name === name) { | ||
blocks.push(element); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
return blocks; | ||
} | ||
function getImports(module: Module): Block[] { | ||
return module.body.filter((block) => block.kind === "Import"); | ||
} | ||
async function fileExists(name: string): Promise<boolean> { | ||
try { | ||
await promises.access(name); | ||
} catch (e) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function runFile(target: Target, fullName: string): void { | ||
let child; | ||
switch (target) { | ||
case "js": { | ||
child = spawnSync(`npx`, [ `node`, `${fullName}` ], { | ||
stdio: "inherit", | ||
encoding: "utf-8", | ||
}); | ||
break; | ||
} | ||
case "ts": { | ||
child = spawnSync(`npx`, [ `ts-node`, `${fullName}` ], { | ||
stdio: "inherit", | ||
encoding: "utf-8", | ||
}); | ||
break; | ||
} | ||
} | ||
} | ||
type CliCommand = "init" | "compile" | "test"; | ||
function parseCliCommand(): Result<string, CliCommand> { | ||
@@ -119,2 +23,4 @@ if (typeof process.argv[2] === "undefined") { | ||
return Ok("test"); | ||
case "install": | ||
return Ok("install"); | ||
default: { | ||
@@ -126,259 +32,2 @@ return Err(`Unknown command \`${process.argv[2]}\``); | ||
const compileParser = parser([ | ||
longFlag("files", "File names to be compiled", variableList(string())), | ||
longFlag( | ||
"target", | ||
"Target TS, JS or Derw output", | ||
oneOf([ "ts", "js", "derw", "elm" ]) | ||
), | ||
longFlag("output", "Output directory name", string()), | ||
longFlag( | ||
"verify", | ||
"Run typescript compiler on generated files to ensure valid output", | ||
empty() | ||
), | ||
longFlag("debug", "Show a parsed object tree", empty()), | ||
longFlag("only", "Only show a particular object", string()), | ||
longFlag("run", "Should be run via ts-node/node", empty()), | ||
longFlag("format", "Format the files given in-place", empty()), | ||
longFlag("quiet", "Keep it short and sweet", empty()), | ||
bothFlag("h", "help", "This help text", empty()), | ||
]); | ||
function showHelp(): void { | ||
console.log("Let's write some Derw code"); | ||
console.log("To get started:"); | ||
console.log("Initialize the current directory via `init`"); | ||
console.log("Or provide entry files via `--files`"); | ||
console.log("Or run me without args inside a package directory"); | ||
console.log(help(compileParser)); | ||
} | ||
async function getDerwFiles(): Promise<string[]> { | ||
return await (await readdir("./src")) | ||
.map((file) => path.join("src", file)) | ||
.filter((file) => file.endsWith("derw")); | ||
} | ||
async function compileFiles( | ||
program: Program, | ||
isInPackageDirectory: boolean | ||
): Promise<void> { | ||
const debugMode = program.flags["debug"].isPresent; | ||
const files = isInPackageDirectory | ||
? await getDerwFiles() | ||
: (program.flags.files.arguments as Ok<string[]>).value; | ||
const isFormat = program.flags.format.isPresent; | ||
const outputDir = program.flags.output.isPresent | ||
? (program.flags.output.arguments as Ok<string>).value | ||
: "./"; | ||
const isStdout = outputDir === "/dev/stdout"; | ||
if (!isStdout) { | ||
await ensureDirectoryExists(outputDir); | ||
} | ||
const target = isFormat | ||
? "derw" | ||
: program.flags.target.isPresent | ||
? (program.flags.target.arguments as Ok<Target>).value | ||
: "ts"; | ||
const shouldRun = program.flags.run.isPresent; | ||
const isQuiet = program.flags.quiet.isPresent; | ||
if (!isQuiet) { | ||
if (isInPackageDirectory) { | ||
console.log("Compiling package..."); | ||
} | ||
console.log(`Generating ${files.length} files...`); | ||
} | ||
const processedFiles: string[] = [ ]; | ||
await Promise.all( | ||
files.map(async function compile(fileName) { | ||
if (processedFiles.indexOf(fileName) > -1) { | ||
return; | ||
} | ||
processedFiles.push(fileName); | ||
const dotParts = fileName.split("."); | ||
const extension = dotParts[dotParts.length - 1]; | ||
if (extension !== "derw") { | ||
console.log("Warning: Derw files should be called .derw"); | ||
console.log( | ||
`Try renaming ${fileName} to ${dotParts | ||
.slice(0, -1) | ||
.join(".")}.derw` | ||
); | ||
} | ||
const derwContents = (await promises.readFile(fileName)).toString(); | ||
const isMain = files.indexOf(fileName) > -1; | ||
const parsed = derwParser.parse( | ||
derwContents, | ||
isMain ? "Main" : fileName | ||
); | ||
if (parsed.errors.length > 0) { | ||
console.log(`Failed to parse ${fileName} due to:`); | ||
console.log(parsed.errors.join("\n")); | ||
return; | ||
} | ||
const dir = path.dirname(fileName); | ||
const imports: string[] = [ ]; | ||
getImports(parsed).forEach((import_: Block) => { | ||
import_ = import_ as Import; | ||
import_.modules.forEach((module) => { | ||
if (module.namespace === "Global") return; | ||
const moduleName = module.name.slice(1, -1); | ||
imports.push(path.normalize(path.join(dir, moduleName))); | ||
}); | ||
}); | ||
for (const import_ of imports) { | ||
const fileWithDerwExtension = import_ + `.derw`; | ||
const isDerw = await fileExists(fileWithDerwExtension); | ||
if (isDerw) { | ||
await compile(fileWithDerwExtension); | ||
continue; | ||
} | ||
// check if ts/js versions of the file exist | ||
const fileWithTsExtension = import_ + `.ts`; | ||
const fileWithJsExtension = import_ + `.js`; | ||
let doesFileExist = false; | ||
if (await fileExists(fileWithTsExtension)) { | ||
doesFileExist = true; | ||
} else if (await fileExists(fileWithJsExtension)) { | ||
doesFileExist = true; | ||
} | ||
if (!doesFileExist) { | ||
console.log( | ||
`Warning! Failed to find \`${import_}\` as either derw, ts or js` | ||
); | ||
} | ||
} | ||
if (debugMode) { | ||
if (program.flags["only"].isPresent) { | ||
if (program.flags["only"].arguments.kind === "err") { | ||
console.log(program.flags.only.arguments.error); | ||
} else { | ||
const name = ( | ||
program.flags["only"].arguments as Ok<string> | ||
).value; | ||
const blocks = filterBodyForName(parsed, name); | ||
console.log(`Filtering for ${name}...`); | ||
console.log(util.inspect(blocks, true, null, true)); | ||
} | ||
return; | ||
} | ||
console.log(util.inspect(parsed, true, null, true)); | ||
return; | ||
} | ||
const generated = generate(target, parsed); | ||
if (program.flags.verify.isPresent && target === "ts") { | ||
const output = compileTypescript(generated); | ||
if (output.kind === "err") { | ||
console.log( | ||
`Failed to compile ${fileName} due to`, | ||
output.error.map((e) => e.messageText).join("\n") | ||
); | ||
} else { | ||
console.log(`Successfully compiled ${fileName}`); | ||
} | ||
} | ||
if (isStdout) { | ||
console.log(generated); | ||
return; | ||
} | ||
if (fileName.indexOf("/") > -1) { | ||
const dirName = fileName.split("/").slice(0, -1).join("/"); | ||
await ensureDirectoryExists(path.join(outputDir, dirName)); | ||
} | ||
const outputName = dotParts.slice(0, -1).join(".") + "." + target; | ||
const fullName = path.join(outputDir, outputName); | ||
await writeFile(fullName, generated); | ||
if (shouldRun) { | ||
runFile(target, fullName); | ||
} | ||
}) | ||
); | ||
if (!isQuiet) { | ||
console.log("Processed:", processedFiles); | ||
} | ||
} | ||
async function copyTSconfig() { | ||
const tsconfig = { | ||
compilerOptions: { | ||
target: "es2017", | ||
module: "commonjs", | ||
declaration: true, | ||
outDir: "./build/", | ||
rootDirs: [ "src" ], | ||
strict: true, | ||
moduleResolution: "node", | ||
types: [ "node" ], | ||
esModuleInterop: true, | ||
skipLibCheck: true, | ||
forceConsistentCasingInFileNames: true, | ||
}, | ||
include: [ "src/**/*" ], | ||
exclude: [ "node_modules/**" ], | ||
}; | ||
if (await fileExists("tsconfig.json")) { | ||
console.log("Already got a tsconfig!"); | ||
return -1; | ||
} | ||
await writeFile("tsconfig.json", JSON.stringify(tsconfig, null, 4)); | ||
} | ||
async function init() { | ||
const packageName = path.basename(process.cwd()); | ||
const package_ = Package(packageName, [ ], [ ]); | ||
if (await fileExists("derw-package.json")) { | ||
console.log("Package already initialized!"); | ||
return -1; | ||
} | ||
await writeFile("derw-package.json", exportPackage(package_)); | ||
await copyTSconfig(); | ||
await ensureDirectoryExists("src"); | ||
} | ||
async function runTests(isInPackageDirectory: boolean): Promise<void> { | ||
if (!isInPackageDirectory) { | ||
console.log("Must run tests from the root of a package directory."); | ||
process.exit(1); | ||
} | ||
await runner(); | ||
} | ||
function showCommandHelp(): void { | ||
@@ -391,3 +40,3 @@ console.log("To get started:"); | ||
export async function main(): Promise<void> { | ||
export async function main(): Promise<number> { | ||
const command = parseCliCommand(); | ||
@@ -398,53 +47,24 @@ | ||
showCommandHelp(); | ||
return; | ||
process.exit(1); | ||
} | ||
const isInPackageDirectory = await fileExists("derw-package.json"); | ||
switch (command.value) { | ||
case "compile": { | ||
const program = parse(compileParser, process.argv); | ||
if (program.flags["h/help"].isPresent) { | ||
showHelp(); | ||
return; | ||
} | ||
const errors = allErrors(program); | ||
if (errors.length > 0) { | ||
console.log("Errors:"); | ||
console.log(errors.join("\n")); | ||
process.exit(1); | ||
} | ||
const isInPackageDirectory = await fileExists("derw-package.json"); | ||
if (!program.flags.files.isPresent && !isInPackageDirectory) { | ||
console.log("You must provide at least one file via --files"); | ||
console.log("Or be in a directory wit derw-package.json."); | ||
process.exit(1); | ||
} | ||
await compileFiles(program, isInPackageDirectory); | ||
return; | ||
await compileFiles(isInPackageDirectory); | ||
return 0; | ||
} | ||
case "init": { | ||
await init(); | ||
console.log("Project initialized!"); | ||
console.log("Put your files in `src`"); | ||
console.log("Compile your project via `derw compile`"); | ||
console.log("Run tests via `derw test`"); | ||
return; | ||
await init(isInPackageDirectory); | ||
return 0; | ||
} | ||
case "install": { | ||
await install(isInPackageDirectory); | ||
return 0; | ||
} | ||
case "test": { | ||
const program = parse(compileParser, process.argv); | ||
const errors = allErrors(program); | ||
if (errors.length > 0) { | ||
console.log("Errors:"); | ||
console.log(errors.join("\n")); | ||
process.exit(1); | ||
} | ||
const isInPackageDirectory = await fileExists("derw-package.json"); | ||
await compileFiles(program, isInPackageDirectory); | ||
await compileFiles(isInPackageDirectory); | ||
await runTests(isInPackageDirectory); | ||
return; | ||
return 0; | ||
} | ||
@@ -451,0 +71,0 @@ } |
@@ -184,2 +184,29 @@ import { | ||
function generateTopLevelType(type_: Type): string { | ||
switch (type_.kind) { | ||
case "GenericType": { | ||
return generateType(type_); | ||
} | ||
case "FixedType": { | ||
if (type_.name === "List") { | ||
return generateType(type_); | ||
} | ||
const args = type_.args.filter( | ||
(type_) => | ||
type_.kind === "GenericType" || type_.kind === "FixedType" | ||
); | ||
if (args.length === 0) { | ||
return type_.name; | ||
} | ||
return `${type_.name} ${args.map(generateType).join(" ")}`; | ||
} | ||
case "FunctionType": { | ||
return generateType(type_); | ||
} | ||
} | ||
} | ||
function generateType(type_: Type): string { | ||
@@ -448,3 +475,3 @@ switch (type_.kind) { | ||
const returnType = generateType(function_.returnType); | ||
const returnType = generateTopLevelType(function_.returnType); | ||
const body = generateExpression(function_.body); | ||
@@ -463,3 +490,3 @@ | ||
const body = prefixLines(generateExpression(constDef.value), 4); | ||
const typeDef = generateType(constDef.type); | ||
const typeDef = generateTopLevelType(constDef.type); | ||
return ` | ||
@@ -466,0 +493,0 @@ ${constDef.name}: ${typeDef} |
@@ -201,2 +201,29 @@ import { | ||
function generateTopLevelType(type_: Type): string { | ||
switch (type_.kind) { | ||
case "GenericType": { | ||
return generateType(type_); | ||
} | ||
case "FixedType": { | ||
if (type_.name === "List") { | ||
return generateType(type_); | ||
} | ||
const args = type_.args.filter( | ||
(type_) => | ||
type_.kind === "GenericType" || type_.kind === "FixedType" | ||
); | ||
if (args.length === 0) { | ||
return typeMapNameLookup(type_.name); | ||
} | ||
return `${type_.name} ${args.map(generateType).join(" ")}`; | ||
} | ||
case "FunctionType": { | ||
return generateType(type_); | ||
} | ||
} | ||
} | ||
function generateType(type_: Type): string { | ||
@@ -480,3 +507,3 @@ switch (type_.kind) { | ||
const returnType = generateType(function_.returnType); | ||
const returnType = generateTopLevelType(function_.returnType); | ||
const body = generateExpression(function_.body); | ||
@@ -495,3 +522,3 @@ | ||
const body = prefixLines(generateExpression(constDef.value), 4); | ||
const typeDef = generateType(constDef.type); | ||
const typeDef = generateTopLevelType(constDef.type); | ||
return ` | ||
@@ -498,0 +525,0 @@ ${constDef.name}: ${typeDef} |
@@ -79,2 +79,17 @@ import { | ||
export function addDependency( | ||
dependency: Dependency, | ||
package_: Package | ||
): Package { | ||
for (const dep of package_.dependencies) { | ||
if (dep.name === dependency.name) { | ||
dep.version = dependency.version; | ||
return package_; | ||
} | ||
} | ||
package_.dependencies.push(dependency); | ||
return package_; | ||
} | ||
export function exportPackage(package_: Package): string { | ||
@@ -84,3 +99,3 @@ const dependencies: Record<string, string> = {}; | ||
for (const dependency of package_.dependencies) { | ||
dependencies[dependency.name] = dependencies.version; | ||
dependencies[dependency.name] = dependency.version; | ||
} | ||
@@ -87,0 +102,0 @@ |
@@ -292,2 +292,28 @@ import path from "path"; | ||
function generateTopLevelType(type_: Type): string { | ||
switch (type_.kind) { | ||
case "GenericType": { | ||
return generateType(type_); | ||
} | ||
case "FixedType": { | ||
if (type_.name === "List") { | ||
return generateType(type_); | ||
} | ||
const args = type_.args.filter( | ||
(type_) => | ||
type_.kind === "GenericType" || type_.kind === "FixedType" | ||
); | ||
if (args.length === 0) { | ||
return type_.name; | ||
} | ||
return `${type_.name}<${args.map(generateType).join(", ")}>`; | ||
} | ||
case "FunctionType": { | ||
return generateType(type_); | ||
} | ||
} | ||
} | ||
function generateType(type_: Type): string { | ||
@@ -649,3 +675,3 @@ switch (type_.kind) { | ||
const returnType = generateType(function_.returnType); | ||
const returnType = generateTopLevelType(function_.returnType); | ||
const isSimpleBody = isSimpleValue(function_.body.kind); | ||
@@ -676,3 +702,3 @@ | ||
const body = generateExpression(constDef.value); | ||
const typeDef = generateType(constDef.type); | ||
const typeDef = generateTopLevelType(constDef.type); | ||
return ` | ||
@@ -679,0 +705,0 @@ const ${constDef.name}: ${typeDef} = ${body}; |
@@ -136,2 +136,18 @@ import { Err, Ok, Result } from "@eeue56/ts-core/build/main/lib/result"; | ||
} | ||
if ( | ||
first.kind === "FixedType" && | ||
first.args.length === 0 && | ||
second.kind === "GenericType" | ||
) { | ||
return true; | ||
} | ||
if ( | ||
second.kind === "FixedType" && | ||
second.args.length === 0 && | ||
first.kind === "GenericType" | ||
) { | ||
return true; | ||
} | ||
return false; | ||
@@ -138,0 +154,0 @@ } |
Sorry, the diff of this file is too big to display
472515
74
14014
6
2