Support file path argument to elm-pages run command.

This commit is contained in:
Dillon Kearns 2023-03-23 12:01:09 -07:00
parent 3bbe3badfd
commit e2c07f5676
2 changed files with 79 additions and 18 deletions

View File

@ -18,6 +18,7 @@ import { default as which } from "which";
import * as commander from "commander";
import { runElmCodegenInstall } from "./elm-codegen.js";
import { packageVersion } from "./compatibility-key.js";
import { resolveInputPathOrModuleName } from "./resolve-elm-module.js";
const Argument = commander.Argument;
const Option = commander.Option;
@ -85,22 +86,21 @@ async function main() {
});
program
.command("run <moduleName>")
.command("run <elmModulePath>")
.description("run an elm-pages script")
.allowUnknownOption()
.allowExcessArguments()
.action(async (moduleName, options, options2) => {
.action(async (elmModulePath, options, options2) => {
const unprocessedCliOptions = options2.args.splice(
options2.processedArgs.length,
options2.args.length
);
if (!/^[A-Z][a-zA-Z0-9_]*(\.[A-Z][a-zA-Z0-9_]*)*$/.test(moduleName)) {
throw `Invalid module name "${moduleName}", must be in the format of an Elm module`;
}
const { moduleName, projectDirectory, sourceDirectory } =
resolveInputPathOrModuleName(elmModulePath);
console.log({ moduleName, projectDirectory });
const splitModuleName = moduleName.split(".");
const expectedFilePath = path.join(
process.cwd(),
"script/src/",
sourceDirectory,
`${splitModuleName.join("/")}.elm`
);
if (!fs.existsSync(expectedFilePath)) {
@ -115,24 +115,24 @@ async function main() {
await runElmCodegenInstall();
}
ensureDirSync("./script/elm-stuff");
ensureDirSync("./script/elm-stuff/elm-pages/.elm-pages");
ensureDirSync(`${projectDirectory}/elm-stuff`);
ensureDirSync(`${projectDirectory}/elm-stuff/elm-pages/.elm-pages`);
await fs.promises.writeFile(
path.join("./script/elm-stuff/elm-pages/.elm-pages/Main.elm"),
path.join(
`${projectDirectory}/elm-stuff/elm-pages/.elm-pages/Main.elm`
),
generatorWrapperFile(moduleName)
);
let executableName = "lamdera";
try {
await which("lamdera");
executableName = "elm";
} catch (error) {
await which("elm");
console.log("Falling back to Elm");
executableName = "elm";
}
await rewriteElmJson(
"./script/elm.json",
"./script/elm-stuff/elm-pages/elm.json",
`${projectDirectory}/elm.json`,
`${projectDirectory}/elm-stuff/elm-pages/elm.json`,
{ executableName }
);
@ -170,20 +170,20 @@ async function main() {
});
const portsPath = await portBackendTaskCompiled;
process.chdir("./script");
process.chdir(projectDirectory);
// TODO have option for compiling with --debug or not (maybe allow running with elm-optimize-level-2 as well?)
await build.compileCliApp({ debug: "debug", executableName });
process.chdir("../");
fs.renameSync(
"./script/elm-stuff/elm-pages/elm.js",
"./script/elm-stuff/elm-pages/elm.cjs"
`${projectDirectory}/elm-stuff/elm-pages/elm.js`,
`${projectDirectory}/elm-stuff/elm-pages/elm.cjs`
);
await renderer.runGenerator(
unprocessedCliOptions,
portsPath
? await import(url.pathToFileURL(path.resolve(portsPath)).href)
: null,
await requireElm("./script/elm-stuff/elm-pages/elm.cjs"),
await requireElm(`${projectDirectory}/elm-stuff/elm-pages/elm.cjs`),
moduleName
);
} catch (error) {

View File

@ -0,0 +1,61 @@
import * as fs from "node:fs";
import * as path from "node:path";
function findNearestElmJson(filePath) {
function searchForElmJson(directory) {
if (directory === "/") {
return null;
}
const elmJsonPath = path.join(directory, "elm.json");
return fs.existsSync(elmJsonPath)
? elmJsonPath
: searchForElmJson(path.dirname(directory));
}
return searchForElmJson(path.dirname(filePath));
}
function getElmModuleName(inputPath) {
const filePath = path.normalize(
path.isAbsolute(inputPath) ? inputPath : path.resolve(inputPath)
);
const elmJsonPath = findNearestElmJson(filePath);
if (!elmJsonPath) {
throw new Error("No elm.json found");
}
const elmJson = JSON.parse(fs.readFileSync(elmJsonPath, "utf8"));
const sourceDirectories = elmJson["source-directories"];
const projectDirectory = path.dirname(elmJsonPath);
const matchingSourceDir = sourceDirectories
.map((sourceDir) => path.join(projectDirectory, sourceDir))
.find((absoluteSourceDir) => filePath.startsWith(absoluteSourceDir));
if (!matchingSourceDir) {
throw new Error(
"File is not in any source-directories specified in elm.json"
);
}
const relativePath = path.relative(matchingSourceDir, filePath);
const moduleName = relativePath.replace(path.extname(relativePath), "");
return { projectDirectory, moduleName, sourceDirectory: matchingSourceDir };
}
export function resolveInputPathOrModuleName(inputPathOrModuleName) {
if (
/^[A-Z][a-zA-Z0-9_]*(\.[A-Z][a-zA-Z0-9_]*)*$/.test(inputPathOrModuleName)
) {
return {
moduleName: inputPathOrModuleName,
projectDirectory: "./script",
sourceDirectory: "./script/src",
};
} else {
return getElmModuleName(inputPathOrModuleName);
}
}