literate-elm
Version:
Runs literate Elm code blocks and calculates Elm expressions
151 lines • 6.71 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureEnvironment = void 0;
const fs_extra_1 = require("fs-extra");
const object_hash_1 = __importDefault(require("object-hash"));
const path_1 = require("path");
const auxFiles_1 = require("./shared/auxFiles");
const gc_1 = require("./shared/gc");
const tools_1 = require("./shared/tools");
const cacheShapeVersion = "v1";
const cacheDirectorySalt = "v0.19";
const defaultTimeout = 30000;
const projectExpiryWithErrors = 1000 * 60;
const projectExpiryWithNoElmFound = 1000 * 5;
const prepareElmApplication = (directory, dependencies, sourceDirectories) => __awaiter(void 0, void 0, void 0, function* () {
// install dependencies
yield (0, tools_1.initializeElmProject)(directory);
let userRequestsJsonPackage = false;
for (const packageName in dependencies) {
if (Object.prototype.hasOwnProperty.call(dependencies, packageName)) {
const packageVersion = dependencies[packageName];
yield (0, tools_1.installElmPackage)(directory, packageName, packageVersion);
if (packageName === "elm/json") {
userRequestsJsonPackage = true;
}
}
}
if (!userRequestsJsonPackage) {
yield (0, tools_1.installElmPackage)(directory, "elm/json", "latest");
}
// add sourceDirectories to elm.json
yield (0, tools_1.patchElmJson)(directory, (elmJson) => {
elmJson["source-directories"] = [...sourceDirectories, "."];
});
});
const resolvePathToMetadata = (workingDirectory) => {
return (0, path_1.resolve)(workingDirectory, "literate-elm-metadata.json");
};
const ensureEnvironment = (spec, literateElmDirectory, timeout = defaultTimeout) => __awaiter(void 0, void 0, void 0, function* () {
const now = +new Date();
const currentCacheDirectory = (0, path_1.resolve)(literateElmDirectory, cacheShapeVersion);
try {
yield (0, auxFiles_1.ensureUnlocked)(literateElmDirectory);
}
catch (e) {
// resetting directory lock (garbage collector in another process could get stuck)
(0, auxFiles_1.unlock)(literateElmDirectory);
}
yield (0, gc_1.collectGarbageIfNeeded)(literateElmDirectory);
const specDirectory = (0, path_1.resolve)(currentCacheDirectory, `spec${(0, object_hash_1.default)({ spec, CACHE_DIRECTORY_SALT: cacheDirectorySalt })}`);
try {
yield (0, fs_extra_1.ensureDir)(specDirectory);
const specJsonPath = (0, path_1.resolve)(specDirectory, `spec.json`);
if (!(yield (0, fs_extra_1.pathExists)(specJsonPath))) {
yield (0, fs_extra_1.writeFile)(specJsonPath, JSON.stringify(spec, null, 4), "utf8");
}
}
catch (e) {
return {
spec,
workingDirectory: specDirectory,
metadata: {
createdAt: now,
status: "error",
errorMessage: `Could not create directory ${specDirectory}`,
},
};
}
// attempt to restore existing environment
const currentWorkingDirectoryLocatorPath = (0, path_1.resolve)(specDirectory, "wd");
try {
yield (0, auxFiles_1.ensureUnlocked)(specDirectory, timeout);
const workingSubdirectory = yield (0, fs_extra_1.readFile)(currentWorkingDirectoryLocatorPath, "utf8");
const workingDirectory = (0, path_1.resolve)(specDirectory, workingSubdirectory);
const metadata = JSON.parse(yield (0, fs_extra_1.readFile)(resolvePathToMetadata(workingDirectory), "utf8"));
if (metadata.expiresAt && metadata.expiresAt < now) {
throw new Error("Expired");
}
return {
metadata,
spec,
workingDirectory,
};
}
catch (e) {
//
}
try {
yield (0, auxFiles_1.lock)(specDirectory);
const workingSubdirectory = `wd${now}`;
const workingDirectory = (0, path_1.resolve)(specDirectory, workingSubdirectory);
yield (0, fs_extra_1.ensureDir)(workingDirectory);
let metadata;
try {
yield prepareElmApplication(workingDirectory, spec.dependencies, spec.sourceDirectories);
metadata = {
status: "ready",
createdAt: now,
};
}
catch (e) {
yield (0, auxFiles_1.touch)((0, path_1.resolve)(workingDirectory, "ProgramFORGC"));
const isElmFound = `${e.message}`.indexOf("ENOENT") === -1 &&
`${e.message}`.indexOf("No elm global binary available") === -1;
metadata = {
status: "error",
createdAt: now,
expiresAt: now +
(isElmFound ? projectExpiryWithErrors : projectExpiryWithNoElmFound),
errorMessage: isElmFound
? e.message
: 'I am having trouble finding Elm on your machine. Is it installed? Check by opening a terminal window and typing "elm --version" (without quotation marks). If you have recently installed Elm, try restarting your machine.',
};
}
yield (0, fs_extra_1.writeFile)(resolvePathToMetadata(workingDirectory), JSON.stringify(metadata, null, 2), "utf8");
yield (0, fs_extra_1.writeFile)(currentWorkingDirectoryLocatorPath, workingSubdirectory, "utf8");
return {
spec,
workingDirectory,
metadata,
};
}
catch (e) {
return {
spec,
workingDirectory: specDirectory,
metadata: {
createdAt: now,
status: "error",
errorMessage: e.message,
},
};
}
finally {
yield (0, auxFiles_1.unlock)(specDirectory);
}
});
exports.ensureEnvironment = ensureEnvironment;
//# sourceMappingURL=ensureEnvironment.js.map