Created
December 7, 2017 11:27
-
-
Save ccapndave/8ea0e0a89fe4e16c222e77f9043fe592 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//import { File, WorkFlowContext, Plugin } from "fuse-box"; | |
import { File, WorkFlowContext, Plugin } from "../../fuse-box/.dev"; | |
import { ChildProcess } from "child_process"; | |
import { resolve, relative } from "path"; | |
import { readFile } from "fs"; | |
import { tmpName } from "tmp"; | |
import * as spawn from "cross-spawn"; | |
import { findAllDependencies } from "find-elm-dependencies" | |
const tmp = () => | |
new Promise((resolve, reject) => | |
tmpName((err, path) => (err ? reject(err) : resolve(path))) | |
); | |
export interface ElmPluginOptions { | |
warn?: boolean; | |
debug?: boolean; | |
} | |
export class ElmPluginClass implements Plugin { | |
// Match Elm files | |
public test: RegExp = /\.elm$/; | |
public context: WorkFlowContext; | |
public options: ElmPluginOptions; | |
constructor(options: ElmPluginOptions = {}) { | |
this.options = { ...options }; | |
} | |
public init(context: WorkFlowContext): void { | |
this.context = context; | |
context.allowExtension(".elm"); | |
} | |
public getElmMakePath(): string { | |
try { | |
return resolve("node_modules/.bin/elm-make"); | |
} catch (_) {} | |
return "elm-make"; | |
} | |
public async transform(file: File): Promise<any> { | |
if (this.context.useCache) { | |
if (file.loadFromCache()) { | |
const lastChangedFile = file.context.convertToFuseBoxPath(this.context.bundle.lastChangedFile); | |
const isElmDependency = file.analysis.dependencies.indexOf(lastChangedFile) >= 0; | |
// We never go any deeper since elm-make bundles for us | |
file.analysis.dependencies = []; | |
if (!isElmDependency) { | |
return; | |
} | |
} | |
} | |
file.loadContents(); | |
// Get the path to elm-make | |
const elmMakePath: string = this.getElmMakePath(); | |
// Create temporary JS file | |
const tmpFilename: string = `${await tmp()}.js`; | |
return new Promise((resolve, reject) => { | |
// Construct the arguments for elm-make | |
const args = [ | |
"--yes", | |
"--output", | |
tmpFilename, | |
this.options.warn ? "--warn" : null, | |
this.options.debug ? "--debug" : null, | |
file.absPath | |
].filter(x => x !== null); | |
const proc: ChildProcess = spawn(elmMakePath, args, { stdio: "inherit" }); | |
proc.on("error", (err: NodeJS.ErrnoException) => { | |
if (err.code === "ENOENT") { | |
reject( | |
`Could not find Elm compiler @ "${elmMakePath}" | |
\nHave you installed elm yet? If not, please install "elm" via npm` | |
); | |
} else if (err.code === "EACCES") { | |
reject( | |
`Elm compiler @ "${elmMakePath}" did not have permission to run | |
\nYou may need give it executable permissions` | |
); | |
} else { | |
reject( | |
`Error attempting to run Elm compiler @ "${elmMakePath}" \n ${err}` | |
); | |
} | |
}); | |
proc.on("close", (code: Number) => { | |
if (code === 0) { | |
readFile(tmpFilename, (err: NodeJS.ErrnoException, data: Buffer) => { | |
if (err) { | |
reject(err); | |
} else { | |
file.contents = data.toString(); | |
findAllDependencies(file.absPath) | |
.then((paths: string[]) => { | |
if (this.context.useCache) { | |
// Make the paths relative to the home directory | |
paths = paths.map(path => relative(this.context.homeDir, path)); | |
file.analysis.dependencies = paths; | |
this.context.emitJavascriptHotReload(file); | |
this.context.cache.writeStaticCache(file, file.sourceMap); | |
file.analysis.dependencies = []; | |
} | |
resolve(file); | |
}) | |
.catch((err: string) => { | |
reject(err); | |
}); | |
resolve(file); | |
} | |
}); | |
} else { | |
reject("Failed to compile Elm."); | |
} | |
}); | |
}); | |
} | |
} | |
export const ElmPlugin = (options?: ElmPluginOptions) => | |
new ElmPluginClass(options); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment